Compare commits

...
21 Commits
Author SHA1 Message Date
izatwin 637009abf8 hw5 start 2024-04-18 20:29:22 -04:00
izatwin e391687a2e project 4 2024-04-18 20:29:15 -04:00
izatwin 3cad683e98 delete unecessary files 2024-04-12 10:44:49 -04:00
izatwin 51f720ad9f p4 start 2024-04-12 10:39:46 -04:00
izatwin f7697e992f hw4 stuff 2024-04-12 10:39:38 -04:00
izatwin 8a25672da0 moved p3 2024-04-09 15:06:59 -04:00
izatwin 4478618a17 deleted random stuff 2024-03-27 10:22:15 -04:00
izatwin 4321264563 project 4 skeleton 2024-03-27 10:18:16 -04:00
izatwin 1bf1e773a5 hw4 q1 and q2 done 2024-03-27 10:11:47 -04:00
izatwin 611513ed9d hw4 q1 and q2 done 2024-03-26 14:40:24 -04:00
izatwin 45f8e38c1f add tex gitignore 2024-03-26 10:50:39 -04:00
izatwin f5f90d89a3 hw4 start 2024-03-26 10:49:16 -04:00
izatwin 66e8626fc9 midterm studies 2024-03-26 10:48:58 -04:00
izatwin aab3637fd7 hw3 2024-03-26 10:48:48 -04:00
izatwin ef53299240 hw2q3 done 2024-03-02 14:46:52 -05:00
izatwin 659352e992 start hw2q3 2024-03-02 11:45:26 -05:00
izatwin fde465354e More Notes 2024-03-02 11:45:15 -05:00
izatwin 5bd0da5970 finished Project 2 2024-03-02 11:45:02 -05:00
izatwin b011a30ab6 initial commit with everything 2024-02-14 11:33:04 -05:00
izatwin 2c4360df9b Merge remote-tracking branch 'refs/remotes/origin/main' 2024-02-14 11:31:29 -05:00
izatwin eb15a96eca initial commit 2024-02-14 11:31:02 -05:00
296 changed files with 606484 additions and 0 deletions
+302
View File
@@ -43,3 +43,305 @@ buildNumber.properties
# JDT-specific (Eclipse Java Development Tools)
.classpath
# ---> TeX
## Core latex/pdflatex auxiliary files:
*.aux
*.lof
*.log
*.lot
*.fls
*.out
*.toc
*.fmt
*.fot
*.cb
*.cb2
.*.lb
## Intermediate documents:
*.dvi
*.xdv
*-converted-to.*
# these rules might exclude image files for figures etc.
# *.ps
# *.eps
# *.pdf
## Generated if empty string is given at "Please type another file name for output:"
.pdf
## Bibliography auxiliary files (bibtex/biblatex/biber):
*.bbl
*.bcf
*.blg
*-blx.aux
*-blx.bib
*.run.xml
## Build tool auxiliary files:
*.fdb_latexmk
*.synctex
*.synctex(busy)
*.synctex.gz
*.synctex.gz(busy)
*.pdfsync
## Build tool directories for auxiliary files
# latexrun
latex.out/
## Auxiliary and intermediate files from other packages:
# algorithms
*.alg
*.loa
# achemso
acs-*.bib
# amsthm
*.thm
# beamer
*.nav
*.pre
*.snm
*.vrb
# changes
*.soc
# comment
*.cut
# cprotect
*.cpt
# elsarticle (documentclass of Elsevier journals)
*.spl
# endnotes
*.ent
# fixme
*.lox
# feynmf/feynmp
*.mf
*.mp
*.t[1-9]
*.t[1-9][0-9]
*.tfm
#(r)(e)ledmac/(r)(e)ledpar
*.end
*.?end
*.[1-9]
*.[1-9][0-9]
*.[1-9][0-9][0-9]
*.[1-9]R
*.[1-9][0-9]R
*.[1-9][0-9][0-9]R
*.eledsec[1-9]
*.eledsec[1-9]R
*.eledsec[1-9][0-9]
*.eledsec[1-9][0-9]R
*.eledsec[1-9][0-9][0-9]
*.eledsec[1-9][0-9][0-9]R
# glossaries
*.acn
*.acr
*.glg
*.glo
*.gls
*.glsdefs
*.lzo
*.lzs
*.slg
*.slo
*.sls
# uncomment this for glossaries-extra (will ignore makeindex's style files!)
# *.ist
# gnuplot
*.gnuplot
*.table
# gnuplottex
*-gnuplottex-*
# gregoriotex
*.gaux
*.glog
*.gtex
# htlatex
*.4ct
*.4tc
*.idv
*.lg
*.trc
*.xref
# hyperref
*.brf
# knitr
*-concordance.tex
# TODO Uncomment the next line if you use knitr and want to ignore its generated tikz files
# *.tikz
*-tikzDictionary
# listings
*.lol
# luatexja-ruby
*.ltjruby
# makeidx
*.idx
*.ilg
*.ind
# minitoc
*.maf
*.mlf
*.mlt
*.mtc[0-9]*
*.slf[0-9]*
*.slt[0-9]*
*.stc[0-9]*
# minted
_minted*
*.pyg
# morewrites
*.mw
# newpax
*.newpax
# nomencl
*.nlg
*.nlo
*.nls
# pax
*.pax
# pdfpcnotes
*.pdfpc
# sagetex
*.sagetex.sage
*.sagetex.py
*.sagetex.scmd
# scrwfile
*.wrt
# svg
svg-inkscape/
# sympy
*.sout
*.sympy
sympy-plots-for-*.tex/
# pdfcomment
*.upa
*.upb
# pythontex
*.pytxcode
pythontex-files-*/
# tcolorbox
*.listing
# thmtools
*.loe
# TikZ & PGF
*.dpth
*.md5
*.auxlock
# titletoc
*.ptc
# todonotes
*.tdo
# vhistory
*.hst
*.ver
# easy-todo
*.lod
# xcolor
*.xcp
# xmpincl
*.xmpi
# xindy
*.xdy
# xypic precompiled matrices and outlines
*.xyc
*.xyd
# endfloat
*.ttt
*.fff
# Latexian
TSWLatexianTemp*
## Editors:
# WinEdt
*.bak
*.sav
# Texpad
.texpadtmp
# LyX
*.lyx~
# Kile
*.backup
# gummi
.*.swp
# KBibTeX
*~[0-9]*
# TeXnicCenter
*.tps
# auto folder when using emacs and auctex
./auto/*
*.el
# expex forward references with \gathertags
*-tags.tex
# standalone packages
*.sta
# Makeindex log files
*.lpz
# xwatermark package
*.xwm
# REVTeX puts footnotes in the bibliography by default, unless the nofootinbib
# option is specified. Footnotes are the stored in a file with suffix Notes.bib.
# Uncomment the next line to have this generated file ignored.
#*Notes.bib
Binary file not shown.
+157
View File
@@ -0,0 +1,157 @@
\documentclass{article}
\usepackage[utf8]{inputenc}
\usepackage{amsfonts}
\usepackage{amsmath, amssymb, textcomp, gensymb}
\usepackage[a4paper, total={6in, 8in}]{geometry}
\usepackage{graphicx}
\usepackage{enumerate}
\title{CS 448 Spring 2024 Homework 1}
\author{Sean Rettig}
\begin{document}
\maketitle
\section*{Question 1. (0.50 pts)}
\begin{enumerate}[(a)]
\item Discuss the main capabilities that should be provided by a DBMS
\item Highlight the difference of using a database system with respect to the following approaches. Please, make sure to highlight the benefits offered by a DBMS.
\begin{enumerate}[1.]
\item Traditional file systems
\item In-memory storage
\end{enumerate}
\end{enumerate}
\hrule
\begin{enumerate}[(a)]
\item One of the main capabilities that should be provided by a databse include a self describing nature. The database shouldn't
just store it's own data, but it should also store a complete definition of the database structure and it's constraints.
Another capability should be an insulation between programs and data, otherwise called program-data independence.
This allows changing data structures and storage organization without having to change the DBMS access programs.
Thirdly, there is data abstraction. The DBMS should provide a conceptual representation of it's data, and should hide the actual physical implementation.
The database should also support multiple view of the data.
The user should not be limited to the actual positioning of the data, and should be able to view it in multiple ways.
Finally, the database should facilitate sharing of data and multiuser transaction processing. Multiple users should be able to access the data at the same time.
\item \begin{enumerate}[1.]
\item The traditional filesystem does not include the main characteristics of a DBMS well. There is no self describing nature in a filesystem,
The program or software needs to know where the information is stored to be able to access it. There is no conceptual representation of the data either.
Additionally, there are not multiple views of the data. Finally, sharing information is very difficult because traditional filesystems are very user focused,
so if someone has information stored in their own filesystem place, it is not readily accessible by anyone else.
\item It is not explicitely designated how in-memory storage would be designed. However, if the application software is storing everything in-memory and in the program that is running,
all it takes is for the program to stop or the computer to shut down and the data will be gone.
\end{enumerate}
\end{enumerate}
\newpage
\section*{Question 2. (0.50 pts)}
Cite some examples of integrity constraints that you think can apply to the database shown in
Figure 1.2 in the textbook. Please, provide at least two examples for each type of the following
constraints: unique constraints and referential integrity constraints
\hrule
\vspace{.5cm}
\noindent
Unique: Lets say that each section must have a unique section\_identifier, and each student must have a unique student\_number.
\\\\
\noindent
Referential: Each student\_number in the grade report must refer to a student in STUDENT. Each section identifier in GRADE\_REPORT must
refer to a section\_identifier in SECTION
\section*{Question 3. (0.25 pts)}
What is the difference between a database schema and a database state? Please, use examples to
support your answer.
\hrule
\vspace{.5cm}
\noindent
The database schema is the description of the database and what information it holds, and how it all relates to each other.
The database state is the current data actually in the database.\\\\
For example, in Figure 1.2, the database schema for the STUDENT table says that it includes the students name, Student\_number, Class, and Major.
The database state includes actual student names, and the rest of the information like Name: Smith, Student\_number: 17, Class: 1, Major: CS and then other students as well.
\section*{Question 4. (0.50 pts)}
\begin{enumerate}[(a)]
\item What is logical independence and physical independence? Please, use examples to
support your answer.
\item Which one is harder to achieve? Explain why.
\end{enumerate}
\hrule
\vspace{.5cm}
\noindent
\begin{enumerate}[(a)]
\item Data independence refers to the capacity to change different levels in the three scheme architecture without affecting each other.
Logical independence is the ability to change the conceptual schema, while physical independence refers to the ability to change the internal schema.
\\\\
If you had logical independence, you could add a row to GRADE\_REPORT in Figure 1.2 and all the external views that
call for data that is in the other columns will not be affected at all.
If you had physical independence, you could change the way that GRADE\_REPORT is actually stored in the
DBMS by creating a better way of accessing the data. The conceptual schema wouldn't cahnge and neither would the external schema.
\item Logical independence is harder to achieve. This is because it allows structural and constraint changes, but you cannot affect application programs.
\end{enumerate}
\section*{Question 5. (0.50 pts)}
What are the different components of a DBMS? Discuss the importance and need of each
component.
\hrule
\vspace{.5cm}
\noindent
\begin{itemize}
\item \textbf{Interfaces for DBA staff, Casual Users, Application Programmers, and Parametric Users}: This is important because
the data is needed to be accessed, but not everyone needs the same type of access. Some need more advanced while others need simpler access.
\item \textbf{DDL Compiler}: This prcoesses schema definitions. This is important to create the catalog.
\item \textbf{Query Optimizer}: This component takes queries and looks for ways to optimize them. Either by consulting the catalog or through other means.
It is important because it improves performance.
\item \textbf{Precompiler}: This extracts DML commands and sends them to the DML compiler for compilation into object code.
This is important to be able to communicate to the database.
\item \textbf{Runtime Database processor}: This executes the commands, query plans, and transactions. This is important in accessing the database.
\item \textbf{Stored Data Manager}: This uses basic operating system services for carrying out low-level IO to disk and main memory. It's important
because the low-level IO needs to reach the higher level calls.
\item \textbf{Concurrency control and Backup and Recovery systems}: Handle concurrency access as well as backup and recovery of the database. These are important
to support the main capabilities of the database being concurrency access and then another important feature of backup.
\end{itemize}
\section*{Question 6. (0.50 pts)}
\begin{enumerate}[(a)]
\item What is a user transaction?
\item What properties must be maintained for a transaction by the database system? Please,
discuss each property using an example to support your argument.
\end{enumerate}
\hrule
\vspace{.5cm}
\noindent
\begin{enumerate}[(a)]
\item A transaction, as the textbook says, is an execuiting program or process. It can include one or more database accesses.
It can read or update records as well.
\item Properties that the DBMS have must include isolation as well as atomicity.
Isolation ensures that each transaction takes place without effecting other transactions. This means that if I had one transaction asking
for all the students in one class, but in the middle of that transaction I update the students in the class, the first transaction will
have the same result as if I didn't do the second one.
Atomicity ensures that either all the databse operations in a transaction are executed or none are. For example,
if, in my transaction, I calculated GPA of all students and added that to their records, but my second operation doesn't complete successfully, then the first part of
of my transaction will not execute.
\end{enumerate}
\section*{Question 7. (0.25 pts)}
Why is accessing a disk block expensive? Discuss the time components involved in accessing a
disk block.
\vspace{.5cm}
\hrule
\vspace{.5cm}
\noindent
It is expensive for a couple of reasons. Given the address, the disk controller must physically position the read/write head on the
on the correct track. This is called seek time and can take anywhere from 5 to 10 msec.\\
After seek time there is also rotational delay. This is waiting for the beginning of the desired block to rotate into position under the read/write head. For a 15,000 rpm (pretty fast) disk, the average rotational
delay is 2 msec.\\
After that there is actually transferring the data. This is called the block transfer time, which can differ between disks and OSes, but is generally less than
the seek time and rotational delay.\\
Thus, disk access time = seek time + rotational delay + block transfer time.
\end{document}
Binary file not shown.
Binary file not shown.
+75
View File
@@ -0,0 +1,75 @@
\documentclass{article}
\usepackage[utf8]{inputenc}
\usepackage{enumerate}
\usepackage{amsfonts}
\usepackage{amsmath, amssymb, textcomp, gensymb}
\usepackage[a4paper, total={6in, 8in}]{geometry}
\usepackage{graphicx}
\title{CS 448 Spring 2024 Homework 2}
\author{Sean Rettig}
\begin{document}
\maketitle
\section{}
Suppose that each of the following operations is applied directly to the database state shown in
the Figure 5.6 and database schema in the Figure 5.7 in the Textbook (7th Edition). The figures
are also shown in slides 5-31 and slides 5-37 respectively. Discuss all integrity constraints
violated by each operation (including the tables affected), if any, and the different ways to
enforce the constraints (without modifying the operation) with some relevant explanation(s). For
example, the operation Delete the PROJECT tuple with Pname = 'ProductX' violates a
referential integrity constraint with WORKS\_ON. Possible ways to enforce the operation are: (i)
reject the delete; (ii) delete cascade (delete all tuples in WORKS\_ON that correspond to Pname
= 'ProductX').\\
\begin{enumerate} [(a)]
\item Delete the WORKS\_ON tuples with Essn = '999887777'.
\item Modify the Super\_ssn attribute of the EMPLOYEE tuple with Ssn = '999887777' to NULL.
\item Insert tuple $<$'555123456', Phil, 'M', 2000-12-01, 'Son'$>$ into Dependent.
\item Delete the DEPT\_LOCATIONS tuples where Dnumber < 3.
\end{enumerate}
\textbf{Answer:}
\begin{enumerate} [(a)]
\item This operation is acceptable. There are no integrity Constraints that are violated.
Referencing Figure 5.6, it deletes two tuples in the WORKED\_ON table.
\item This operation is acceptable. There are no integrity constraints that are violated.
Referencing Figure 5.6, it modifies a single value of a tuple in the EMPLOYEE table to NULL.
\item This insertion violates the referential integrity constraint specified on
Essn in DEPENDENT because no corresponding referenced tuple exists in
EMPLOYEE with Ssn = 555123456. Possible ways to enforce the operation are: (i) reject the delete;
\item This deletion is acceptable. There are no integrity constraints that are violated.
Referencing Figure 5.6, it deletes a single tuple in the DEPT\_LOCATIONS table.
\end{enumerate}
\section{}
Database design often involves decisions about the storage of attributes. For example, the SSN can
be subdivided in groups and stored in multiple attributes for security/validation purpose (validate
the last four digits). Another example is the address, which can be stored as a single attribute or
split in multiple attributes (City, State, ZIP, Street Address).
\begin{enumerate} [(a)]
\item Discuss specific scenarios where it is useful to store the address as one attribute (i.e., a
text field) or multiple attributes (i.e., separate fields for city, state, zip, number). Explain
your answer.
\item Discuss at least 2 additional scenarios of information that can benefit of such decisions
(split in multiple attributes)? You need to use other examples i.e. other than “Address”
and “SSN”. Explain you answer.
\end{enumerate}
\textbf{Answer:}
\begin{enumerate} [(a)]
\item Storing an address as a single text field can make information insertion and storage much simpler,
since all the user would need to insert is the string with their address, and all that would need to be stored is the string.
However, storing multiple attributes like this could be helpful if one needs to gather information about the address. If you wanted to sort
all users by city, or state, it would be hard if the address was just a text field instead of split into attributes by city, state, zip, number that
you could easily query.
\item (1st scenario) A phone number could benefit from being split into multiple attributes. It could consist of the country code of origin,
the area code, the telephone prefix, and line number. The first two could be usefull information to use within queries.\\
\\
(2nd scenario) A Date entry could benefit from being split into multiple attributes. This could allow for further granularity if it
allowed an optional NULL valued seconds and nanoseconds, etc. Additionally, if, for example, you wanted to select all within the month of May, it would be easier to grab
the month number instead of parsing a string of the date.
\end{enumerate}
\end{document}
Binary file not shown.
+128
View File
@@ -0,0 +1,128 @@
import sys
# Use this file to write your queries. Submit this file in Gradescope after finishing your homework.
#TODO: Write your username and answer to each query as a string in the return statements in the functions below.
# Do not change the function names.
#Make sure to test that python prints out the strings (your username and SQL queries) correctly.
#usage:python3 hw1.py
# make sure the program prints out your SQL statements correctly. That means the autograder will read you SQL correctly.
# Running the Python3 file will not execute your SQL statements (just prints them).
def username():
return "srettig" # Write your username here
def query1():
return """
SELECT
Fname,
Minit,
Lname
FROM
cs448_employee ce
WHERE
(
SELECT
COUNT(*)
FROM
cs448_dependent cd
WHERE
ce.Ssn = cd.Essn
) >= 3
AND (
SELECT
SUM(Hours)
FROM
cs448_works_on cwo
WHERE
ce.Ssn = cwo.Essn
) >= 30;
"""
def query2():
return """
UPDATE
cs448_dept_location
Set
Dlocation = 'Lafayette'
WHERE
Dnumber in
(
SELECT
Dnumber
From
cs448_department cd
WHERE
(
SELECT
COUNT(*)
FROM
cs448_employee ce
WHERE
cd.Dnumber = ce.Dnumber
) < 5)
"""
def query3():
return """
DELETE
FROM
cs448_dependent
WHERE
Essn in
(
SELECT
ce.Ssn
From
cs448_employee ce,
cs448_employee cem
WHERE
ce.Super_ssn = cem.Ssn
AND ce.Dnumber != cem.Dnumber)
"""
def query4():
return """
SELECT
Fname,
Minit,
Lname
From
cs448_employee
WHERE
(Salary,
Ssn) IN (
SELECT
MAX(Salary),
Ssn
FROM
cs448_employee ce2
Group BY
ce2.Dnumber)
"""
#Do not edit below
def main():
query_options = {1: query1(), 2: query2(), 3: query3(), 4: query4()}
if len(sys.argv) == 1:
if username() == "username":
print("Make sure to change the username function to return your username.")
return
else:
print(username())
for query in query_options.values():
print(query)
elif len(sys.argv) == 2:
if sys.argv[1] == "username":
print(username())
else:
print(query_options[int(sys.argv[1])])
if __name__ == "__main__":
main()
Binary file not shown.
Binary file not shown.

After

Width:  |  Height:  |  Size: 911 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 891 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 784 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 850 KiB

Binary file not shown.
+95
View File
@@ -0,0 +1,95 @@
\documentclass{article}
\usepackage[utf8]{inputenc}
\usepackage{enumitem}
\usepackage{amsfonts}
\usepackage{amsmath, amssymb, textcomp, gensymb}
\usepackage[a4paper, total={6in, 8in}]{geometry}
\usepackage{graphicx}
\title{CS 448 Spring 2024 Homework 3}
\author{Sean Rettig}
\begin{document}
\maketitle
\section{ (1.0 Point)}
Specify the following queries in relational algebra (R.A.) on the COMPANY database schema
shown in Figure 5.5 in the Textbook. Do not use any other information from the database state
on Figure 5.6 to build the queries.
\begin{enumerate} [label=(\alph*)]
\item List names of employees (Fname, Minit, Lname) who are directly supervised by a female supervisor.
\item List names of employees (Fname, Minit, Lname) who are NOT assigned to every project.
\item List names of employees (Fname, Minit, Lname) in Departments with locations in Houston or Sugarland.
\item List the names of department managers (Fname, Minit, Lname) who have no dependents.
\end{enumerate}
\textbf{Answer:}\\
\begin{enumerate} [label=(\alph*)]
\item $\pi_{\text{Fname, Minit, Lname}}(\text{EMPLOYEE}* (\rho_{(\text{Super\_ssn})}(\pi_{\text{Ssn}}(\sigma_{\text{Sex=female}}(\text{EMPLOYEE})))))$
\item (EMPLOYEE - (EMPLOYEE $\div \pi_{\text{Pnumber}}(\text{PROJECT})$))
\item $\pi_{\text{Fname, Minit, Lname}}($\\
$\text{EMPLOYEE}\bowtie_{\text{Dno=Dnumber}} (\sigma_{\text{Dlocation='Houston' OR Dlocation='Sugarland'}}(\text{DEPT\_LOCATIONS}))$\\
$)$
\item $\pi_{\text{Fname, Minit, Lname}}($\\
$(\text{EMPLOYEE}\bowtie_{\text{Ssn=Mgr\_ssn}}(\text{DEPARTMENT})) * (\pi_{\text{Ssn}}(\text{EMPLOYEE}) - \rho_{(\text{Ssn})}(\pi_{\text{Essn}}(\text{DEPENDENT})))$
\\ $)$
\end{enumerate}
\section{1.0 Point}
Consider SQL queries Q13 and Q4A in Chapter 6.
\begin{enumerate} [label=(\alph*)]
\item Draw the initial query tree for each of these queries, and then show how the query tree is
optimized by the algorithm outlined in Section 19.1.
\item For each query, compare the initial query and the final query tree. Discuss the difference
between each tree.
\end{enumerate}
\noindent
\textbf{Answer:}\\
\textbf{Q13 Unoptimized:}\\
\includegraphics[width=0.8\textwidth]{Q13 UNOPT.jpg}\\
Step 1 specified a break up of any SELECT operations, and that was used to break up the third to final SELECT operation
into multiple cascading SELECT Operations. I used Step 2 and 4 to move the SELECT Operations down as far as they can, as well as combining them
with their respective CARTESION PRODUCT into a JOIN operation. I followed Step 3 by moving the most restricive SELECT
down to the bottom of the tree. Step 5 was used to move project operations as far down the tree as needed.\\
\newpage
\textbf{Q13 Optimized:}\\
\includegraphics[width=0.8\textwidth]{Q13 OPT.jpg}\\
\textbf{Q4A Unoptimized:}\\
\includegraphics[width=0.8\textwidth]{Q4A UNOPT.jpg}\\
Step 1 specified a break up of any SELECT operations, and that was used to break up the two third to final SELECT operations
into multiple cascading SELECT Operations. I used Step 2 and 4 to move the SELECT Operations down as far as they can, as well as combining them
with their respective CARTESION PRODUCT into a JOIN operation. I followed Step 3 by moving the most restricive SELECT operations
down to the bottom of the tree. Step 5 was used to move project operations as far down the tree as needed.\\
\textbf{Q4A Optimized:}\\
\includegraphics[width=0.8\textwidth]{Q4A OPT.jpg}
\newpage
\section{1.0 Point}
Suppose that a disk unit has the following parameters: seek time s = 20 msec; rotational delay rd
= 10 msec; block transfer time btt = 1 msec; block size B = 2400 bytes; interblock gap size G =
600 bytes. An EMPLOYEE file has the following fields: Ssn , 9 bytes; Last\_name , 20 bytes;
First\_name , 20 bytes; Middle\_init , 1 byte; Birth\_date , 10 bytes; Address , 35 bytes; Phone , 12
bytes; Supervisor\_ssn , 9 bytes; Department , 4 bytes; Job\_code , 4 bytes; deletion marker, 1
byte. The EMPLOYEE file has r = 30,000 records, fixed-length format, and unspanned blocking.
Write appropriate formulas and calculate the following values for the above EMPLOYEE file:
\begin{enumerate} [label=(\alph*)]
\item \textbf{Calculate the record size R (including the deletion marker), the blocking factor bfr, and the number of disk blocks b.}\\
Record size:\\
Ssn + Last\_name + First\_name + Middle\_init + Birth\_date + Address + Phone + Supervisor\_ssn + Department + Job\_code + deletion marker\\
\[= 9 + 20 + 20 + 1 + 10 + 35 + 12 + 9 + 4 + 4 + 1 = 125\text{ bytes}\]
$bfr = \lfloor B/R \rfloor = \lfloor 2400 / 125 \rfloor = 19$\\
Number of disk blocks required $= \lceil r / bfr \rceil = \lceil 30000 / 19 \rceil = 1579$ blocks
\item \textbf{Calculate the wasted space in each disk block because of the unspanned organization.}\\
Unused space $= B - (bfr * R) = 2400 - (19 *125) = 25$ bytes
\item \textbf{Calculate the transfer rate tr and the bulk transfer rate btr for this disk unit (see Appendix B in the textbook for definitions of tr and btr).}\\
$tr = B/btt = 2400 / 1 = 2400$ bytes/msec\\
$btr = (B/(B+G)) * tr = (2400/(2400+600)) * 2400 = 1920$ bytes/msec
\item \textbf{Calculate the average number of block accesses needed to search for an arbitrary record in the file, using linear search.}\\
average block accesses for linear search = $b/2 = 1579 / 2 = 789.5$ blocks
\item \textbf{Calculate in msec the average time needed to search for an arbitrary record in the file,
using linear search, if the file blocks are stored on consecutive disk blocks and double
buffering is used.}\\
Average time to search for an arbitrary record = average blocks * average time = $b/2 * (s+rd+(k*B/btr)) = 1579/2 * (20 + 10 +(1579*(2400/1920))) = 1581960.625$ msec
\end{enumerate}
\end{document}
Binary file not shown.
Binary file not shown.
+153
View File
@@ -0,0 +1,153 @@
\documentclass{article}
\usepackage[utf8]{inputenc}
\usepackage{enumitem}
\usepackage{amsfonts}
\usepackage{amsmath, amssymb, textcomp, gensymb}
\usepackage[a4paper, total={6in, 8in}]{geometry}
\usepackage{graphicx}
\title{CS 448 Spring 2024 Homework 4}
\author{Sean Rettig}
\begin{document}
\maketitle
\section{}
Consider the universal relation R = \{A, B, C, D, E, F, G, H, I, J\} and the set of functional
dependencies F.\\
\\
F =\\
\\
\{\{A, B\}→\{C, D\},\\
\{D\}→\{E, F, G\},\\
\{F, G\}→\{H\},\\
\{A\}→\{I\},\\
\{A, B\}→\{E, G\},\\
\{A, I\} → \{I, J\}\}
\begin{enumerate} [label=(\alph*)]
\item \textbf{What is the closure of the set \{A, D\}?}\\
$\{A, D\}^+ = \{A, D, E, F, G, H, I, J\}$
\item \textbf{What is the key for R?}\\
Key $= \{A, B\}$, since \{A, B\}'s closure includes all atributes.
\item \textbf{What is the minimum cover for the set of functional dependencies F?}\\
Convert to canonical form:\\
\{\{A, B\}→\{C\},\\
\{A, B\}→\{D\},\\
\{D\}→\{E\},\\
\{D\}→\{F\},\\
\{D\}→\{G\},\\
\{F, G\}→\{H\},\\
\{A\}→\{I\},\\
\{A, B\}→\{E\},\\
\{A, B\}→\{G\},\\
\{A, I\} → \{I\}\\
\{A, I\} → \{J\}\}\\
Eliminate extraneous stuff:\\
\{\{A, B\}→\{C\},\\
\{A, B\}→\{D\},\\
\{D\}→\{E\},\\
\{D\}→\{F\},\\
\{D\}→\{G\},\\
\{F, G\}→\{H\},\\
\{A\}→\{I\},\\
\{A, B\}→\{E\},\\
\{A, B\}→\{G\},\\
\{A\} → \{J\}\}\\
Eliminate redundancies:\\
\{\{A, B\}→\{C\},\\
\{A, B\}→\{D\},\\
\{D\}→\{E\},\\
\{D\}→\{F\},\\
\{D\}→\{G\},\\
\{F, G\}→\{H\},\\
\{A\}→\{I\},\\
\{A\} → \{J\}\}\\
\item \textbf{Decompose R into 2NF.}\\
R = \{A, B, C, D, E, F, G, H, I, J\}\\
Split up:\\
$R_1$ = \{\underline{A}, \underline{B}, C, D, E, F, G, H\}; $R_2$ = \{\underline{A}, I, J\}\\
This is because every nonprime element in $R_1$ is fully functionally dependent on \{A, B\}, and every nonprime element in $R_2$ is fully functionally dependent on $\{A\}$.
\item Decompose R into 3NF\\
$R_1$ = \{\underline{A}, \underline{B}, C, D\}; $R_2$ = \{\underline{A}, I, J\}; $R_3$ = \{\underline{D}, E, F, G\} $R_4$ = \{\underline{F}, \underline{G}, H\}\\
\end{enumerate}
\newpage
\section{}
\begin{enumerate} [label=(\alph*)]
\item \textbf{What are the possible sources of the information that defines the functional dependencies
that hold among the attributes of a relation schema? Discuss two possible sources. Explain your
answer.}\\
Functional dependencies must be defined explicitely by someone who knows the semantics of the attributes in the relation.
So what are some possible sources for these semantics?\\
\\
A possible source could be the entity that wants to use the database. Lets say its a company that want's to keep track of laptops. Perhaps they have a bunch of attributes that they
want to be able to keep track of about the laptops. They can put together the attributes and then make some sort of ID for each laptop that has functional dependencies for the relation.\\
\\
Another possible source could be some sort of relationship that is already defined in the nature of whatever you are already trying to model. For example, the relationship between a child and their mother.
There is a functional dependency from the child to the mother because the child can only have one biological mother while the mother could have multiple children.
\item \textbf{What is meant by the closure of a set of functional dependencies? Illustrate with an example.}\\
The closure of a set of FD really just means that it includes all inferences that can be made from a sparser set of functional dependencies. It's the most explicit you can be about a group of relations.\\
For example, if there is a functional dependency between my SSN and me $(A \rightarrow B)$, and also a functional dependency between me and my mother $(B \rightarrow C)$, the closure of the set of those two would also include the functional dependency that can be inferred between my ssn and my mother. $(A \rightarrow C)$.
Thus, the closure of the SSN would be $A^+ = \{A, B, C\}$.
\item \textbf{What is the lossless (or nonadditive) join property of a decomposition? Why is it important?}\\
This property ensures that spurious tuples, or tuples that were not in the original relation before decomposition, do not appear after rejoining the relations.\\
This is important so we can complete the normalization of the data and relations without losing information. We need the benefits that come with normalizing relations, but we cannot sacrifice data to achieve it.
\end{enumerate}
\newpage
\section{}
Consider the following four schedules for transactions T1, T2 and T3:
\begin{enumerate} [label=\alph*]
\item r1(X); r3(X); w1(X); r2(X); w3(X); w2(X)
\item r1(Y); r3(Y); w3(X); w1(X); r2(X); w2(Y)
\item w2(X); r1(Y); w2(Y); r2(X); w2(Y); r3(Y)
\item r3(X); r2(X); w3(X); r1(Y); w1(X); r2(Y)
\item r3(X); r2(X); r1(X); w3(X); w1(X); w2(X)
\end{enumerate}
\begin{enumerate} [label=(\alph*)]
\item For each schedule, specify whether or not the schedule is conflict serializable and why. To
determine if a schedule is conflict serializable you can either use the precedence graph or swap
conflicting operations.
\item Then, for each serializable schedule, give the equivalent serial schedule.
\end{enumerate}
\hrule
\begin{enumerate} [label=(\alph*)]
\item \textbf{r1(X); r3(X); w1(X); r2(X); w3(X); w2(X)}\\
Not-Serializable. There is a cycle between $T_1$ and $T_3$ in the precedence graph.\\
\includegraphics[width=0.5\linewidth]{pred_graph_a.jpg}
\item \textbf{r1(Y); r3(Y); w3(X); w1(X); r2(X); w2(Y)}\\
Serializable.\\
r3(Y); w3(X); r1(Y); w1(X); r2(X); w2(Y)\\
\includegraphics[width=0.5\linewidth]{pred_graph_b.jpg}
\item \textbf{w2(X); r1(Y); w2(Y); r2(X); w2(Y); r3(Y)}\\
Serializable.\\
r1(Y); w2(X); w2(Y); r2(X); w2(Y); r3(Y)\\
\includegraphics[width=0.5\linewidth]{pred_graph_c.jpg}
\item \textbf{r3(X); r2(X); w3(X); r1(Y); w1(X); r2(Y)}\\
Serializable.\\
r2(X); r2(Y); r3(X); w3(X); r1(Y); w1(X)\\
\includegraphics[width=0.5\linewidth]{pred_graph_d.jpg}
\item \textbf{r3(X); r2(X); r1(X); w3(X); w1(X); w2(X)}\\
Not-Serializable. There is a cycle between all edges in the precedence graph.\\
\includegraphics[width=0.5\linewidth]{pred_graph_e.jpg}
\end{enumerate}
\newpage
\section{(0.75 points)}
Consider the following actions taken by transaction T1 on a database with objects X and Y:\\
\textbf{R1(X), W1(X), R1(Y), W1(Y)}\\
Without altering the order of operations of T1, give example schedules with an additional
Transactions T2 (with 4 operations accessing both database objects X and Y) that fulfill the
following conditions:\\
\begin{enumerate} [label=(\alph*)]
\item \textbf{Give an example schedule using two transactions (T1 and T2) which is conflict serializable.}\\
w2(X); r1(X); r2(Y); w2(Y); r2(X); w1(X); r1(Y); w1(Y)\\
The precedence graph shows no cycles.
\item \textbf{Give an example schedule using two transactions (T1 and T2) which is not conflict serializable. Explain why the schedule is not conflict serializable.}\\
w2(X); r1(X); r2(Y); w2(Y); w1(X); r2(X); r1(Y); w1(Y)\\
The precedence graph has a cycle between $T_1$ and $T_2$. $T_1$ writes before $T_2$ reads, but $T_2$ has already written before $T_1$.
\end{enumerate}
\end{document}
Binary file not shown.
Binary file not shown.

After

Width:  |  Height:  |  Size: 191 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 302 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 328 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 359 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 361 KiB

Binary file not shown.
+18
View File
@@ -0,0 +1,18 @@
\documentclass{article}
\usepackage[utf8]{inputenc}
\usepackage{enumitem}
\usepackage{amsfonts}
\usepackage{amsmath, amssymb, textcomp, gensymb}
\usepackage[a4paper, total={6in, 8in}]{geometry}
\usepackage{graphicx}
\title{CS 448 Spring 2024 Homework 5}
\author{Sean Rettig}
\begin{document}
\maketitle
\section{}
\end{document}
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
+24
View File
@@ -0,0 +1,24 @@
# 1/9/24
Claude Shannon? came up with theory of information. You are looking for information and knowledge
You want to integrate all the data. Some centralized warehouse. Utilities to access the data. Queries to let you get the data you care about.
# 1/11/24
Additional DBMS functionality
- Temporal database as well
#### Data Abstraction
- A data model
- Can store as a table
- can store as a tree
- or a network
- Used to hide storage details and present the users with a conceptual view of the database
# 1/16/24
How you store the data is independent from how you access the data.
the very first database model was called the entity relationship model
+17
View File
@@ -0,0 +1,17 @@
target/
pom.xml.tag
pom.xml.releaseBackup
pom.xml.versionsBackup
pom.xml.next
release.properties
dependency-reduced-pom.xml
buildNumber.properties
.mvn/timing.properties
# https://github.com/takari/maven-wrapper#usage-without-binary-jar
.mvn/wrapper/maven-wrapper.jar
# Eclipse m2e generated files
# Eclipse Core
.project
# JDT-specific (Eclipse Java Development Tools)
.classpath
+29
View File
@@ -0,0 +1,29 @@
{
// Use IntelliSense to learn about possible attributes.
// Hover to view descriptions of existing attributes.
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
"version": "0.2.0",
"configurations": [
{
"type": "java",
"name": "test",
"request": "launch",
"mainClass": "test",
"projectName": "cs448p1"
},
{
"type": "java",
"name": "Current File",
"request": "launch",
"mainClass": "${file}"
},
{
"type": "java",
"name": "App",
"request": "launch",
"mainClass": "cs448.App",
"projectName": "cs448p1",
"args": "./data_30MB.tsv 2 nm0000001"
}
]
}
+3
View File
@@ -0,0 +1,3 @@
{
"java.compile.nullAnalysis.mode": "disabled"
}
+32
View File
@@ -0,0 +1,32 @@
<?xml version="1.0" encoding="UTF-8"?>
<module org.jetbrains.idea.maven.project.MavenProjectsManager.isMavenModule="true" type="JAVA_MODULE" version="4">
<component name="NewModuleRootManager" LANGUAGE_LEVEL="JDK_1_7">
<output url="file://$MODULE_DIR$/target/classes" />
<output-test url="file://$MODULE_DIR$/target/test-classes" />
<content url="file://$MODULE_DIR$">
<sourceFolder url="file://$MODULE_DIR$/src/main/java" isTestSource="false" />
<excludeFolder url="file://$MODULE_DIR$/target" />
</content>
<orderEntry type="inheritedJdk" />
<orderEntry type="sourceFolder" forTests="false" />
<orderEntry type="library" name="Maven: org.mapdb:mapdb:3.0.7" level="project" />
<orderEntry type="library" name="Maven: org.jetbrains.kotlin:kotlin-stdlib:1.2.71" level="project" />
<orderEntry type="library" name="Maven: org.jetbrains.kotlin:kotlin-stdlib-common:1.2.71" level="project" />
<orderEntry type="library" name="Maven: org.jetbrains:annotations:13.0" level="project" />
<orderEntry type="library" name="Maven: org.eclipse.collections:eclipse-collections-api:10.0.0" level="project" />
<orderEntry type="library" name="Maven: org.eclipse.collections:eclipse-collections:10.0.0" level="project" />
<orderEntry type="library" name="Maven: org.eclipse.collections:eclipse-collections-forkjoin:10.0.0" level="project" />
<orderEntry type="library" name="Maven: com.google.guava:guava:28.0-jre" level="project" />
<orderEntry type="library" name="Maven: com.google.guava:failureaccess:1.0.1" level="project" />
<orderEntry type="library" name="Maven: com.google.guava:listenablefuture:9999.0-empty-to-avoid-conflict-with-guava" level="project" />
<orderEntry type="library" name="Maven: com.google.code.findbugs:jsr305:3.0.2" level="project" />
<orderEntry type="library" name="Maven: org.checkerframework:checker-qual:2.8.1" level="project" />
<orderEntry type="library" name="Maven: com.google.errorprone:error_prone_annotations:2.3.2" level="project" />
<orderEntry type="library" name="Maven: com.google.j2objc:j2objc-annotations:1.3" level="project" />
<orderEntry type="library" name="Maven: org.codehaus.mojo:animal-sniffer-annotations:1.17" level="project" />
<orderEntry type="library" name="Maven: net.jpountz.lz4:lz4:1.3.0" level="project" />
<orderEntry type="library" name="Maven: org.mapdb:elsa:3.0.0-M5" level="project" />
<orderEntry type="library" scope="TEST" name="Maven: junit:junit:4.11" level="project" />
<orderEntry type="library" scope="TEST" name="Maven: org.hamcrest:hamcrest-core:1.3" level="project" />
</component>
</module>
Binary file not shown.
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
+10
View File
@@ -0,0 +1,10 @@
nconst primaryName birthYear deathYear primaryProfession knownForTitles
nm0000001 Fred Astaire 1899 1987 soundtrack,actor,miscellaneous tt0072308,tt0053137,tt0043044,tt0050419
nm0000002 Lauren Bacall 1924 2014 actress,soundtrack tt0071877,tt0037382,tt0038355,tt0117057
nm0000003 Brigitte Bardot 1934 \N actress,soundtrack,producer tt0054452,tt0049189,tt0059956,tt0057345
nm0000004 John Belushi 1949 1982 actor,writer,soundtrack tt0078723,tt0072562,tt0077975,tt0080455
nm0000005 Ingmar Bergman 1918 2007 writer,director,actor tt0083922,tt0050976,tt0050986,tt0060827
nm0000006 Ingrid Bergman 1915 1982 actress,soundtrack,producer tt0034583,tt0071877,tt0038787,tt0038109
nm0000007 Humphrey Bogart 1899 1957 actor,soundtrack,producer tt0033870,tt0034583,tt0037382,tt0043265
nm0000008 Marlon Brando 1924 2004 actor,soundtrack,director tt0047296,tt0078788,tt0068646,tt0070849
nm0000009 Richard Burton 1925 1984 actor,producer,soundtrack tt0059749,tt0061184,tt0057877,tt0087803
1 nconst primaryName birthYear deathYear primaryProfession knownForTitles
2 nm0000001 Fred Astaire 1899 1987 soundtrack,actor,miscellaneous tt0072308,tt0053137,tt0043044,tt0050419
3 nm0000002 Lauren Bacall 1924 2014 actress,soundtrack tt0071877,tt0037382,tt0038355,tt0117057
4 nm0000003 Brigitte Bardot 1934 \N actress,soundtrack,producer tt0054452,tt0049189,tt0059956,tt0057345
5 nm0000004 John Belushi 1949 1982 actor,writer,soundtrack tt0078723,tt0072562,tt0077975,tt0080455
6 nm0000005 Ingmar Bergman 1918 2007 writer,director,actor tt0083922,tt0050976,tt0050986,tt0060827
7 nm0000006 Ingrid Bergman 1915 1982 actress,soundtrack,producer tt0034583,tt0071877,tt0038787,tt0038109
8 nm0000007 Humphrey Bogart 1899 1957 actor,soundtrack,producer tt0033870,tt0034583,tt0037382,tt0043265
9 nm0000008 Marlon Brando 1924 2004 actor,soundtrack,director tt0047296,tt0078788,tt0068646,tt0070849
10 nm0000009 Richard Burton 1925 1984 actor,producer,soundtrack tt0059749,tt0061184,tt0057877,tt0087803
Binary file not shown.
+94
View File
@@ -0,0 +1,94 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>edu.cs.purdue</groupId>
<artifactId>cs448p1</artifactId>
<version>1.0-SNAPSHOT</version>
<name>cs448p1</name>
<!-- FIXME change it to the project's website -->
<url>http://www.example.com</url>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.source>1.7</maven.compiler.source>
<maven.compiler.target>1.7</maven.compiler.target>
</properties>
<dependencies>
<!-- https://mvnrepository.com/artifact/org.mapdb/mapdb -->
<dependency>
<groupId>org.mapdb</groupId>
<artifactId>mapdb</artifactId>
<version>3.0.7</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.11</version>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<pluginManagement><!-- lock down plugins versions to avoid using Maven defaults (may be moved to parent pom) -->
<plugins>
<!-- clean lifecycle, see https://maven.apache.org/ref/current/maven-core/lifecycles.html#clean_Lifecycle -->
<plugin>
<artifactId>maven-clean-plugin</artifactId>
<version>3.1.0</version>
</plugin>
<!-- default lifecycle, jar packaging: see https://maven.apache.org/ref/current/maven-core/default-bindings.html#Plugin_bindings_for_jar_packaging -->
<plugin>
<artifactId>maven-resources-plugin</artifactId>
<version>3.0.2</version>
</plugin>
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.8.0</version>
</plugin>
<plugin>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.22.1</version>
</plugin>
<plugin>
<artifactId>maven-jar-plugin</artifactId>
<version>3.0.2</version>
</plugin>
<plugin>
<artifactId>maven-install-plugin</artifactId>
<version>2.5.2</version>
</plugin>
<plugin>
<artifactId>maven-deploy-plugin</artifactId>
<version>2.8.2</version>
</plugin>
<!-- site lifecycle, see https://maven.apache.org/ref/current/maven-core/lifecycles.html#site_Lifecycle -->
<plugin>
<artifactId>maven-site-plugin</artifactId>
<version>3.7.1</version>
</plugin>
<plugin>
<artifactId>maven-project-info-reports-plugin</artifactId>
<version>3.0.0</version>
</plugin>
<plugin>
<artifactId>maven-assembly-plugin</artifactId>
<configuration>
<archive>
<manifest>
<mainClass>cs448.App</mainClass>
</manifest>
</archive>
<descriptorRefs>
<descriptorRef>jar-with-dependencies</descriptorRef>
</descriptorRefs>
</configuration>
</plugin>
</plugins>
</pluginManagement>
</build>
</project>
@@ -0,0 +1,54 @@
package cs448;
import java.io.*;
public class App
{
public static void main( String[] args )
{
String input_file_path = args[0];
int backend = Integer.parseInt(args[1]);
String id = args[2];
project1 p = new project1();
long startts;
String[] column_names = {"nconst", "primaryName", "birthYear", "deathYear", "primaryProfession", "knownForTitles"};
try {
switch (backend){
case 0:
startts = System.nanoTime();
System.out.println(p.select_file(input_file_path,id,column_names));
System.out.println("Elapsed time in (ns): "+(System.nanoTime()-startts));
break;
case 1:
startts = System.nanoTime();
p.load_mainmemory(input_file_path);
System.out.println("Load: elapsed time in (ns): "+(System.nanoTime()-startts));
startts = System.nanoTime();
System.out.println(p.select_mainmemory(id,column_names));
System.out.println("Query: elapsed time in (ns): "+(System.nanoTime()-startts));
break;
case 2:
startts = System.nanoTime();
p.load_mapdb(input_file_path);
System.out.println("Load: elapsed time in (ns): "+(System.nanoTime()-startts));
startts = System.nanoTime();
System.out.println(p.select_mapdb(id,column_names));
System.out.println("Query: elapsed time in (ns): "+(System.nanoTime()-startts));
break;
default:
System.out.println("Syntax: project1 path/to/datafile 0|1|2 id");
}
}
catch(IOException e){
e.printStackTrace();
}
catch (OutOfMemoryError e){
System.gc();
e.printStackTrace();
}
finally {
p.db.close();
}
}
}
@@ -0,0 +1,171 @@
package cs448;
import org.mapdb.DB;
import org.mapdb.DBMaker;
import org.mapdb.Serializer;
import java.io.IOException;
import java.util.Dictionary;
import java.util.HashMap;
import java.util.Hashtable;
import java.util.Scanner;
import java.util.concurrent.ConcurrentMap;
import java.io.File;
import java.lang.StringBuilder;
/**
* A class to compare different storage backends.
*
* @author Sean Rettig
* @version January 22, 2024
*/
public class project1 {
/* Data structure for Main-memory back-end */
HashMap<String,Dictionary<String, String>> mm_map = new HashMap<String,Dictionary<String, String>>();
/* Data structure for MapDB persistent storage*/
String dbfile = "data.db";
DB db = DBMaker.fileDB(dbfile).make();
// use this for MapDB storage
ConcurrentMap mapdb = db.hashMap("map").make();
void load_mainmemory(String file_path) throws IOException {
Scanner sc = new Scanner((new File(file_path)));
String line = "";
while (sc.hasNextLine()) {
line = sc.nextLine();
String[] row = line.split("\t");
Dictionary<String, String> row_dict = new Hashtable<>();
row_dict.put("primaryName", row[1]);
row_dict.put("birthYear", row[2]);
row_dict.put("deathYear", row[3]);
row_dict.put("primaryProfession", row[4]);
row_dict.put("knownForTitles", row[5]);
mm_map.put(row[0], row_dict);
}
}
void load_mapdb(String file_path) throws IOException{
Scanner sc = new Scanner((new File(file_path)));
String line = "";
while (sc.hasNextLine()) {
line = sc.nextLine();
String[] row = line.split("\t");
Dictionary<String, String> row_dict = new Hashtable<>();
row_dict.put("primaryName", row[1]);
row_dict.put("birthYear", row[2]);
row_dict.put("deathYear", row[3]);
row_dict.put("primaryProfession", row[4]);
row_dict.put("knownForTitles", row[5]);
mapdb.put(row[0], row_dict);
}
}
String select_file(String file_path, String key, String[] column_names) throws IOException{
Scanner sc = new Scanner(new File(file_path));
String line = "";
while (sc.hasNextLine()) {
line = sc.nextLine();
if (line.contains(key)) {
sc.close();
break;
}
}
if (line != "") {
String[] row = line.split("\t");
StringBuilder sb = new StringBuilder();
for (String col_name : column_names) {
switch (col_name) {
case "nconst":
sb.append(row[0]);
break;
case "primaryName":
sb.append(row[1]);
break;
case "birthYear":
sb.append(row[2]);
break;
case "deathYear":
sb.append(row[3]);
break;
case "primaryProfession":
sb.append(row[4]);
break;
case "knownForTitles":
sb.append(row[5]);
break;
default:
break;
}
sb.append("\t");
}
line = sb.toString();
}
return line;
}
String select_mainmemory(String key, String[] column_names){
StringBuilder sb = new StringBuilder();
Dictionary<String, String> data = mm_map.get(key);
for (String col_name : column_names) {
if (col_name == "nconst") {
sb.append(key);
} else {
sb.append(data.get(col_name));
}
sb.append("\t");
}
return sb.toString();
}
String select_mapdb(String key, String[] column_names){
StringBuilder sb = new StringBuilder();
Dictionary<String, String> data = (Dictionary<String, String>) mapdb.get(key);
for (String col_name : column_names) {
if (col_name == "nconst") {
sb.append(key);
} else {
sb.append(data.get(col_name));
}
sb.append("\t");
}
return sb.toString();
}
int fastestLoad(){
// 1: Main-memory Load
// 2: MapDB Load
int fastest = 1;
return fastest;
}
int fastestSelect(){
// 0: File Select
// 1: Main-memory Select
// 2: MapDB Select
int fastest = 1;
return fastest;
}
}
Binary file not shown.
+99
View File
@@ -0,0 +1,99 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>edu.cs.purdue</groupId>
<artifactId>cs448p2</artifactId>
<version>1.0-SNAPSHOT</version>
<name>cs448p2</name>
<url>https://www.cs.purdue.edu/homes/bb/cs448f19/</url>
<properties>
<java.version>10</java.version>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.source>${java.version}</maven.compiler.source>
<maven.compiler.target>${java.version}</maven.compiler.target>
</properties>
<dependencies>
<!-- https://mvnrepository.com/artifact/org.mapdb/mapdb -->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.11</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>minibase</groupId>
<artifactId>bufmgr-project</artifactId>
<version>1.0</version>
<scope>system</scope>
<systemPath>${basedir}/lib/bufmgrAssign.jar</systemPath>
</dependency>
</dependencies>
<build>
<pluginManagement><!-- lock down plugins versions to avoid using Maven defaults (may be moved to parent pom) -->
<plugins>
<!-- clean lifecycle, see https://maven.apache.org/ref/current/maven-core/lifecycles.html#clean_Lifecycle -->
<plugin>
<artifactId>maven-clean-plugin</artifactId>
<version>3.1.0</version>
</plugin>
<!-- default lifecycle, jar packaging: see https://maven.apache.org/ref/current/maven-core/default-bindings.html#Plugin_bindings_for_jar_packaging -->
<plugin>
<artifactId>maven-resources-plugin</artifactId>
<version>3.0.2</version>
</plugin>
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.8.0</version>
<configuration>
<release>${java.version}</release>
</configuration>
</plugin>
<plugin>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.22.1</version>
</plugin>
<plugin>
<artifactId>maven-jar-plugin</artifactId>
<version>3.0.2</version>
</plugin>
<plugin>
<artifactId>maven-install-plugin</artifactId>
<version>2.5.2</version>
</plugin>
<plugin>
<artifactId>maven-deploy-plugin</artifactId>
<version>2.8.2</version>
</plugin>
<!-- site lifecycle, see https://maven.apache.org/ref/current/maven-core/lifecycles.html#site_Lifecycle -->
<plugin>
<artifactId>maven-site-plugin</artifactId>
<version>3.7.1</version>
</plugin>
<plugin>
<artifactId>maven-project-info-reports-plugin</artifactId>
<version>3.0.0</version>
</plugin>
<plugin>
<artifactId>maven-assembly-plugin</artifactId>
<configuration>
<archive>
<manifest>
<mainClass>test.TestDriver</mainClass>
</manifest>
</archive>
<descriptorRefs>
<descriptorRef>jar-with-dependencies</descriptorRef>
</descriptorRefs>
</configuration>
</plugin>
</plugins>
</pluginManagement>
</build>
</project>
@@ -0,0 +1,314 @@
package bufmgr;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.Map;
import java.util.Queue;
import diskmgr.DiskMgrException;
import global.Minibase;
import global.Page;
import global.PageId;
/**
* <h3>Minibase Buffer Manager</h3>
* The buffer manager reads disk pages into a main memory page as needed. The
* collection of main memory pages (called frames) used by the buffer manager
* for this purpose is called the buffer pool. This is just an array of Page
* objects. The buffer manager is used by access methods, heap files, and
* relational operators to read, write, allocate, and de-allocate pages.
*/
public class BufMgr {
// INSTANCE VARIABLES
// Some of these are accessed during the test cases
// DO NOT CHANGE THE BELOW INSTANCE VARIABLE NAMES - you should use them as appropriate in your code
// You may add additional ones as you need to
/** bufPool: the buffer pool. An array of Page objects */
private Page[] bufPool = null;
/** frmDescr: An arracy of FrameDescriptor objects, holding information about the contents of each frame. */
private FrameDescriptor[] frmDescr = null;
/** numOfFrames: the number of frames used for the maximum capacity of the buffer pool */
private int numOfFrames = -1;
/** replacementPolicy: will be set to FIFO when the constructor is called. */
private static String replacementPolicy = "FIFO";
/** map: Hash table to track which frame in the buffer a page is in <Key: PageID, Value: Frame> */
private Map<Integer, Integer> pageMap = new HashMap<>();
//
/** fifo: queue for FIFO page replacement. All unpinned pages will be stored here, with the first element being
* the pageID that was unpinned the longest time ago */
private Queue<Integer> fifo = new LinkedList<>();
// END OF REQUIRED INSTANCE VARIABLES
/**
* Resets a FrameDescriptor to the default values with no pageID
*/
protected void resetFrameDescriptor(int frameId) {
resetFrameDescriptor(frameId, -1);
}
/**
* Resets a FrameDescriptor to the default values with the given pageID
*/
protected void resetFrameDescriptor(int frameId, int pageno) {
frmDescr[frameId].pageno = pageno;
frmDescr[frameId].pinCount = 0;
frmDescr[frameId].dirtyBit = false;
}
/**
* Create the BufMgr object. Allocate pages (frames) for the buffer pool in main
* memory and make the buffer manage aware that the replacement policy is
* specified by replacerArg (e.g., LH, Clock, LRU, MRU, LIRS, etc.).
*
* @param numbufs
* number of buffers in the buffer pool
* @param lookAheadSize
* number of pages to be looked ahead - can be ignored for this assignment
* @param replacementPolicy
* Name of the replacement policy
*/
public BufMgr(int numbufs, int lookAheadSize, String replacementPolicy) {
// we ignore replacementPolicy as there is only one policy implemented in the
// system
numOfFrames = numbufs;
bufPool = new Page[numOfFrames];
frmDescr = new FrameDescriptor[numOfFrames];
this.replacementPolicy = replacementPolicy;
for (int i = 0; i < numOfFrames; i++) {
bufPool[i] = new Page();
frmDescr[i] = new FrameDescriptor();
resetFrameDescriptor(i, -1);
fifo.add(i);
}
}
/**
* Pin a page. First check if this page is already in the buffer pool. If it is,
* increment the pin_count and return a pointer to this page. If the pin_count
* was 0 before the call, the page was a replacement candidate, but is no longer
* a candidate. If the page is not in the pool, choose a frame (from the set of
* replacement candidates) to hold this page, read the page (using the
* appropriate method from diskmgr package) and pin it. Also, must write out the
* old page in chosen frame if it is dirty before reading new page.(You can
* assume that emptyPage==false for this assignment.)
*
* @param pageno
* page number in the Minibase.
* @param page
* the pointer point to the page.
* @throws BufferPoolExceededException if there are no valid replacement candidates when attempting to pin a page not already in memory
* @throws DiskMgrException if there is an error from the DiskMgr layer. This is likely caused by incorrect implementations of other methods in the BufferManager
*/
public void pinPage(PageId pageno, Page page, boolean emptyPage)
throws BufferPoolExceededException, DiskMgrException {
//Check if page already in memory
if (pageMap.containsKey(pageno.pid)) {
// page is already in memory
Integer frameno = pageMap.get(pageno.pid);
frmDescr[frameno].pinCount++;
if (frmDescr[frameno].pinCount == 1) {
//the frame was marked previously removal, we need to undo that.
fifo.remove(frameno);
}
page.setPage(bufPool[frameno]);
} else {
if (fifo.size() > 0) {
// there is a page that can be removed
Integer frameno = fifo.remove();
if (frmDescr[frameno].pageno != -1) {
// the frame is not empty
PageId oldPage = new PageId(frmDescr[frameno].pageno);
pageMap.remove(oldPage.pid);
if (frmDescr[frameno].dirtyBit) {
// the page has been written to, and needs to be written to disk
Minibase.DiskManager.write_page(oldPage, bufPool[frameno]);
}
}
// we now have an empty frame in frameno
// we can grab the new page
Minibase.DiskManager.read_page(pageno, bufPool[frameno]);
page.setPage(bufPool[frameno]);
pageMap.put(pageno.pid, frameno);
resetFrameDescriptor(frameno, pageno.pid);
frmDescr[frameno].pinCount++;
} else {
throw new BufferPoolExceededException("All pages in the buffer pool are pinned.");
}
}
}
/**
* Unpin a page specified by a pageId. This method should be called with
* dirty==true if the client has modified the page. If so, this call should set
* the dirty bit for this frame. Further, if pin_count>0, this method should
* decrement it. If pin_count=0 before this call, throw an exception to report
* error. (For testing purposes, we ask you to throw an exception named
* PageUnpinnedException in case of error.)
*
* @param pageno
* the PageID of the page
* @param dirty
* whether or not the page is dirty
* @throws PageNotFoundException the page is not in memory
* @throws PageUnpinnedException the page is already unpinned
*/
public void unpinPage(PageId pageno, boolean dirty)
throws PageNotFoundException, PageUnpinnedException {
if (!pageMap.containsKey(pageno.pid)) {
throw new PageNotFoundException("the page is not in memory");
}
Integer frameno = pageMap.get(pageno.pid);
if (frmDescr[frameno].pinCount > 0) {
frmDescr[frameno].pinCount--;
if (frmDescr[frameno].pinCount == 0) {
//add to fifo
fifo.add(frameno);
}
} else {
throw new PageUnpinnedException("the page is already unpinned");
}
if (dirty) {
frmDescr[frameno].dirtyBit = true;
}
}
/**
* Allocate new pages. Call DB object to allocate a run of new pages and find a
* frame in the buffer pool for the first page and pin it. (This call allows a
* client of the Buffer Manager to allocate pages on disk.) If buffer is full,
* i.e., you can't find a frame for the first page, ask DB to deallocate all
* these pages, and return null.
*
* @param firstpage
* the address of the first page.
* @param howmany
* total number of allocated new pages.
*
* @return the first page id of the new pages.__ null, if error.
* @throws DiskMgrException if there is an error from the DiskMgr layer. This is likely caused by incorrect implementations of other methods of the Buffer Manager
* @throws BufferPoolExceededException if the new page cannot be pinned after the run is allocated due to the buffer being full. If this exception is thrown, the newly allocated pages should be deallocated
*/
public PageId newPage(Page firstpage, int howmany) throws DiskMgrException, BufferPoolExceededException {
PageId nPage = null;
try {
nPage = Minibase.DiskManager.allocate_page(howmany);
pinPage(nPage, firstpage, false);
return nPage;
} catch (BufferPoolExceededException bee) {
try {
if (nPage != null){
Minibase.DiskManager.deallocate_page(nPage, howmany);
}
} catch (BufMgrException be) {
throw new DiskMgrException("Exception in deallocating page.");
}
throw bee;
} catch (BufMgrException be) {
throw new DiskMgrException("Exception in allocating page.");
}
}
/**
* This method should be called to delete a page that is on disk. This routine
* must call the method in diskmgr package to deallocate the page.
*
* @param pageno
* the page number in the data base.
* @throws PagePinnedException if the page is still pinned
* @throws DiskMgrException if there is an error in the DiskMgr layer. This is likely caused by incorrect implementations in other methods of the Buffer Manager
*/
public void freePage(PageId pageno) throws PagePinnedException, DiskMgrException {
if (pageMap.containsKey(pageno.pid)) {
Integer frameno = pageMap.get(pageno.pid);
if (frmDescr[frameno].pinCount > 0) {
throw new PagePinnedException("The page is still pinned!");
} else {
pageMap.remove(pageno.pid);
resetFrameDescriptor(frameno);
// bufPool[frameno] = new Page();
}
}
}
/**
* Used to flush a particular page of the buffer pool to disk. This method calls
* the write_page method of the diskmgr package.
*
* @param pageid
* the page number in the database.
* @throws PageNotFoundException if the page is not in memory
* @throws DiskMgrException if there is an error in the DiskMgr layer. This is likely caused by incorrect implementations in other methods of the Buffer Manager
*/
public void flushPage(PageId pageid) throws PageNotFoundException, DiskMgrException {
// find the frame holding that page
Integer frameId = pageMap.get(pageid.pid);
if (frameId == null) {
throw new PageNotFoundException(
"BufMgr.flushPage: Page with id " + pageid.pid + " does not exist in the buffer bool.");
} else {
Minibase.DiskManager.write_page(pageid, bufPool[frameId]);
frmDescr[frameId].dirtyBit = false;
}
}
/**
* Used to flush all dirty pages in the buffer pool to disk
* @throws DiskMgrException if there is an error in the DiskMgr layer. This is likely caused by incorrect implementations in other methods of the Buffer Manager
*/
public void flushAllPages() throws DiskMgrException {
for (int i = 0; i < numOfFrames; i++) {
if (frmDescr[i].dirtyBit == true) {
Minibase.DiskManager.write_page(new PageId(frmDescr[i].pageno), bufPool[i]);
frmDescr[i].dirtyBit = false;
}
}
}
/**
* Returns the total number of buffer frames.
*/
public int getNumBuffers() {
return numOfFrames;
}
/**
* Returns the total number of unpinned buffer frames.
*/
public int getNumUnpinned() {
int numUnpinned = 0;
for (int i = 0; i < numOfFrames; i++) {
if (frmDescr[i].pinCount <= 0) {
numUnpinned++;
}
}
return numUnpinned;
}
//*** DO NOT CHANGE ANY EXISTING METHODS BELOW THIS LINE ***
// Accessor methods for use in test cases
public FrameDescriptor getFrameDesc(int frameNum) {
return frmDescr[frameNum];
}
public Page getPageFromFrame(int frameNum) {
return bufPool[frameNum];
}
public Integer getFrameFromPage(PageId pid) {
return pageMap.get(new Integer(pid.pid));
}
}
@@ -0,0 +1,15 @@
package bufmgr;
public class BufMgrException extends Throwable
{
/**
*
*/
private static final long serialVersionUID = -53906392083428894L;
public BufMgrException(String msg)
{
super(msg);
}
}
@@ -0,0 +1,15 @@
package bufmgr;
public class BufferPoolExceededException extends BufMgrException
{
/**
*
*/
private static final long serialVersionUID = -3879729988119933114L;
public BufferPoolExceededException(String msg)
{
super(msg);
}
}
@@ -0,0 +1,16 @@
package bufmgr;
/**
* A frame descriptor; contains info about each page in the buffer pool.
*/
public class FrameDescriptor
{
/** Identifies the frame's page. */
public int pageno = -1;
/** The frame's pin count. */
public int pinCount;
/** The frame's dirty status. */
public boolean dirtyBit;
}
@@ -0,0 +1,16 @@
package bufmgr;
public class PageNotFoundException extends BufMgrException
{
public PageNotFoundException(String msg)
{
super(msg);
}
/**
*
*/
private static final long serialVersionUID = 8527332129053870174L;
}
@@ -0,0 +1,16 @@
package bufmgr;
public class PagePinnedException extends BufMgrException
{
public PagePinnedException(String msg)
{
super(msg);
}
/**
*
*/
private static final long serialVersionUID = 2891505249472036297L;
}
@@ -0,0 +1,17 @@
package bufmgr;
public class PageUnpinnedException extends BufMgrException
{
public PageUnpinnedException(String msg)
{
super(msg);
}
/**
*
*/
private static final long serialVersionUID = 8366005988643934461L;
}
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,21 @@
package diskmgr;
public class DiskMgrException extends Exception {
/**
*
*/
private static final long serialVersionUID = -6796603846181216651L;
public DiskMgrException(String name)
{
super(name);
}
}
@@ -0,0 +1,15 @@
package diskmgr;
public class DuplicateEntryException extends DiskMgrException {
/**
*
*/
private static final long serialVersionUID = -7360431299339776190L;
public DuplicateEntryException(String msg)
{
super(msg);
}
}
@@ -0,0 +1,22 @@
package diskmgr;
public class FileEntryNotFoundException extends DiskMgrException {
/**
*
*/
private static final long serialVersionUID = -5657953921202448803L;
public FileEntryNotFoundException(String msg)
{
super(msg);
}
}
@@ -0,0 +1,21 @@
package diskmgr;
public class FileIOException extends DiskMgrException {
/**
*
*/
private static final long serialVersionUID = 6320388561056052984L;
public FileIOException(String msg)
{
super(msg);
}
}
@@ -0,0 +1,19 @@
package diskmgr;
public class FileNameTooLongException extends DiskMgrException {
/**
*
*/
private static final long serialVersionUID = -4115614718485246811L;
public FileNameTooLongException(String msg)
{
super(msg);
}
}
@@ -0,0 +1,19 @@
package diskmgr;
public class InvalidPageNumberException extends DiskMgrException {
/**
*
*/
private static final long serialVersionUID = 5106265663568991693L;
public InvalidPageNumberException(String msg)
{
super(msg);
}
}
@@ -0,0 +1,18 @@
package diskmgr;
public class InvalidRunSizeException extends DiskMgrException {
/**
*
*/
private static final long serialVersionUID = 1663588077268780074L;
public InvalidRunSizeException(String msg)
{
super(msg);
}
}
@@ -0,0 +1,15 @@
package diskmgr;
public class OutOfSpaceException extends DiskMgrException {
/**
*
*/
private static final long serialVersionUID = 2560165916249758898L;
public OutOfSpaceException(String msg)
{
super(msg);
}
}
@@ -0,0 +1,952 @@
package tests;
import static org.junit.Assert.assertTrue;
import java.io.IOException;
import bufmgr.*;
import org.junit.After;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.FixMethodOrder;
import org.junit.Test;
import org.junit.runners.MethodSorters;
import diskmgr.DiskMgrException;
import diskmgr.OutOfSpaceException;
import global.Convert;
import global.GlobalConst;
import global.Minibase;
import global.Page;
import global.PageId;
@FixMethodOrder(MethodSorters.NAME_ASCENDING)
public class BMTest implements GlobalConst {
public final static boolean OK = true;
public final static boolean FAIL = false;
/** Default database size (in pages). */
private final static int DB_SIZE = 10000;
/** Default buffer pool size (in pages) */
private final static int BUF_SIZE = 100;
/** Default number of pages to be looked ahead */
private final static int LAH_SIZE = 10;
// Filepaths
private static String dbpath;
private static String logpath;
private static final String REMOVE_CMD = "/bin/rm -rf ";
private static String remove_logcmd;
private static String remove_dbcmd;
// Instance variables for tests
private static int numPages;
private static Page pg;
private static PageId pid, first_pid, last_pid;
private void checkFDContents(FrameDescriptor fd, int pgid, int pinCount, boolean dirty) {
String failmsg = "Failed: - ";
boolean passed = true;
if (fd.pageno != pgid) {
failmsg += "FD pagenumber: " + fd.pageno + ", should be " + pgid + " - ";
passed = false;
}
if (fd.pinCount != pinCount) {
failmsg += "FD pincount: " + fd.pinCount + ", should be " + pinCount + " - ";
passed = false;
}
if (fd.dirtyBit != dirty) {
failmsg += "Fd dirty bit: " + fd.dirtyBit + ", should be " + dirty;
passed = false;
}
assertTrue(failmsg, passed);
}
@BeforeClass
public static void setUpBeforeClass() throws Exception {
// Set up remove commands and ensure nothing's left over
String remove_cmd = "/bin/rm -rf ";
dbpath = "/tmp/" + System.getProperty("user.name") + ".minibase-db";
logpath = "/tmp/" + System.getProperty("user.name") + ".minibase-log";
remove_logcmd = REMOVE_CMD + logpath;
remove_dbcmd = REMOVE_CMD + dbpath;
// Commands here is very machine dependent. We assume
// user are on UNIX system here
try {
Runtime.getRuntime().exec(remove_logcmd);
Runtime.getRuntime().exec(remove_dbcmd);
} catch (IOException e) {
System.err.println("" + e);
}
}
@Before
public void setUp() throws Exception {
new Minibase(dbpath, DB_SIZE, BUF_SIZE, LAH_SIZE, "FIFO", false);
numPages = Minibase.BufferManager.getNumUnpinned();
pg = new Page();
pid = new PageId();
first_pid = new PageId();
last_pid = new PageId();
}
@After
public void tearDown() throws Exception {
// Remove anything from previous tests
// Commands here are very machine dependent. We assume
// user are on UNIX system here
try {
Runtime.getRuntime().exec(remove_logcmd);
Runtime.getRuntime().exec(remove_dbcmd);
} catch (IOException e) {
System.err.println("" + e);
}
}
@Test
public void testA_PinPageNotInMemory() {
try {
first_pid = Minibase.BufferManager.newPage(pg, 1);
} catch (DiskMgrException e) {
assertTrue("Unexpected Failure: error with DiskMgr for initial allocation", false);
} catch (BufferPoolExceededException e) {
assertTrue("Unexpected Failure: Buffer Pool Full for initial allocation", false);
}
// Allocated and pinned one page - check that it's in hash table
Integer fnum = Minibase.BufferManager.getFrameFromPage(first_pid);
if (fnum == null)
assertTrue("Failed: page not in hash table", false);
pg = Minibase.BufferManager.getPageFromFrame(fnum);
if (pg == null)
assertTrue("Failed: page not in frame", false);
FrameDescriptor fd = Minibase.BufferManager.getFrameDesc(fnum);
checkFDContents(fd, first_pid.pid, 1, false);
}
@Test
public void testB_PinPinnedPageInMemory() {
try {
first_pid = Minibase.BufferManager.newPage(pg, 1);
} catch (DiskMgrException e) {
assertTrue("Unexpected Failure: error with DiskMgr for initial allocation", false);
} catch (BufferPoolExceededException e) {
assertTrue("Unexpected Failure: Buffer Pool Full for initial allocation", false);
}
try {
Minibase.BufferManager.pinPage(first_pid, pg, false);
} catch (BufferPoolExceededException e) {
assertTrue("Unexpected Failure: Buffer Pool Full for repinning already pinned page", false);
} catch (DiskMgrException e) {
assertTrue("Unexpected Failure: error with DiskMgr pinning pinned page", false);
}
// Allocated and pinned one page twice - check that it's in hash table
Integer fnum = Minibase.BufferManager.getFrameFromPage(first_pid);
if (fnum == null)
assertTrue("Failed: page not in hash table", false);
pg = Minibase.BufferManager.getPageFromFrame(fnum);
if (pg == null)
assertTrue("Failed: page not in frame", false);
FrameDescriptor fd = Minibase.BufferManager.getFrameDesc(fnum);
checkFDContents(fd, first_pid.pid, 2, false);
}
@Test
public void testC_UnpinPinnedPageInMemory() {
try {
first_pid = Minibase.BufferManager.newPage(pg, 1);
} catch (DiskMgrException e) {
assertTrue("Unexpected Failure: error with DiskMgr for initial allocation", false);
} catch (BufferPoolExceededException e) {
assertTrue("Unexpected Failure: Buffer Pool Full for initial allocation", false);
}
try {
Minibase.BufferManager.unpinPage(first_pid, false);
} catch (PageNotFoundException e) {
assertTrue("Unexpected Failure: page not found in hash table when unpinning", false);
} catch (PageUnpinnedException e) {
assertTrue("Unexpected Failure: page already unpinned", false);
}
// Allocated and pinned one page, then unpinned it - check that it's in hash
// table
Integer fnum = Minibase.BufferManager.getFrameFromPage(first_pid);
if (fnum == null)
assertTrue("Failed: page not in hash table after unpinning", false);
pg = Minibase.BufferManager.getPageFromFrame(fnum);
if (pg == null)
assertTrue("Failed: page not in frame after unpinning", false);
FrameDescriptor fd = Minibase.BufferManager.getFrameDesc(fnum);
checkFDContents(fd, first_pid.pid, 0, false);
}
@Test
public void testD_PinUnpinnedPageInMemory() {
try {
first_pid = Minibase.BufferManager.newPage(pg, 1);
} catch (DiskMgrException e) {
assertTrue("Unexpected Failure: error with DiskMgr for initial allocation", false);
} catch (BufferPoolExceededException e) {
assertTrue("Unexpected Failure: Buffer Pool Full for initial allocation", false);
}
try {
Minibase.BufferManager.unpinPage(first_pid, false);
} catch (PageNotFoundException e) {
assertTrue("Unexpected Failure: page not found in hash table when unpinning", false);
} catch (PageUnpinnedException e) {
assertTrue("Unexpected Failure: page already unpinned", false);
}
try {
Minibase.BufferManager.pinPage(first_pid, pg, false);
} catch (BufferPoolExceededException bpe_ex) {
assertTrue("Unexpected Failure: Buffer Pool Full when attempting to repin unpinned page in buffer", false);
} catch (DiskMgrException e) {
assertTrue("Unexpected Failure: error with DiskMgr repinning page", false);
}
// Allocated and pinned one page, then unpinned it, then pinned it again
// check that it's in hash table
Integer fnum = Minibase.BufferManager.getFrameFromPage(first_pid);
if (fnum == null)
assertTrue("Failed: page not in hash table after repinning page", false);
pg = Minibase.BufferManager.getPageFromFrame(fnum);
if (pg == null)
assertTrue("Failed: page not in frame after repinning page", false);
FrameDescriptor fd = Minibase.BufferManager.getFrameDesc(fnum);
checkFDContents(fd, first_pid.pid, 1, false);
}
@Test
public void testE_UnpinUnpinnedPageInMemory() {
try {
first_pid = Minibase.BufferManager.newPage(pg, 1);
} catch (DiskMgrException e) {
assertTrue("Unexpected Failure: error with DiskMgr for initial allocation", false);
} catch (BufferPoolExceededException e) {
assertTrue("Unexpected Failure: Buffer Pool Full for initial allocation", false);
}
try {
Minibase.BufferManager.unpinPage(first_pid, false);
} catch (PageNotFoundException e) {
assertTrue("Unexpected Failure: page not found in hash table when unpinning", false);
} catch (PageUnpinnedException e) {
assertTrue("Unexpected Failure: page already unpinned", false);
}
// Unpin the page twice so that we will be unpinning an unpinned page
try {
Minibase.BufferManager.unpinPage(first_pid, false);
} catch (PageNotFoundException e) {
assertTrue("Unexpected Failure: page not found in hash table when unpinning unpinned page", false);
} catch (PageUnpinnedException e) {
assertTrue(true);
return;
}
// If we get here, the expected exception was not returned
assertTrue("Failed: PageUnpinnedException not properly thrown", false);
}
@Test
public void testF_UnpinDirtyPage() {
try {
first_pid = Minibase.BufferManager.newPage(pg, 1);
} catch (DiskMgrException e) {
assertTrue("Unexpected Failure: error with DiskMgr for initial allocation", false);
} catch (BufferPoolExceededException e) {
assertTrue("Unexpected Failure: Buffer Pool Full for initial allocation", false);
}
try {
Minibase.BufferManager.unpinPage(first_pid, true);
} catch (PageNotFoundException e) {
assertTrue("Unexpected Failure: page not found in hash table when unpinning", false);
} catch (PageUnpinnedException e) {
assertTrue("Unexpected Failure: page already unpinned", false);
}
// Allocated and pinned one page, then unpinned it as dirty
// check that it's in hash table
Integer fnum = Minibase.BufferManager.getFrameFromPage(first_pid);
if (fnum == null)
assertTrue("Failed: page not in hash table after unpinning", false);
pg = Minibase.BufferManager.getPageFromFrame(fnum);
if (pg == null)
assertTrue("Failed: page not in frame after unpinning", false);
FrameDescriptor fd = Minibase.BufferManager.getFrameDesc(fnum);
checkFDContents(fd, first_pid.pid, 0, true);
}
@Test
public void testG_UnpinPageNotInMemory() {
try {
first_pid = Minibase.BufferManager.newPage(pg, 2);
} catch (DiskMgrException e) {
assertTrue("Unexpected Failure: error with DiskMgr for initial allocation", false);
} catch (BufferPoolExceededException e) {
assertTrue("Unexpected Failure: Buffer Pool Full for initial allocation", false);
}
try {
Minibase.BufferManager.unpinPage(first_pid, false);
} catch (PageNotFoundException e) {
assertTrue("Unexpected Failure: page not found in hash table while unpinning", false);
} catch (PageUnpinnedException e) {
assertTrue("Unexpected Failure: page already unpinned", false);
}
// Allocated two pages and pinned/unpinned first one
// Now attempt to unpin second, never-pinned page
pid = new PageId(first_pid.pid + 1);
try {
Minibase.BufferManager.unpinPage(pid, false);
} catch (PageNotFoundException e) {
assertTrue(true);
return;
} catch (PageUnpinnedException e) {
assertTrue(
"Unexpected Failure: PageUnpinnedException thrown, but should have returned HashNotFoundException",
false);
}
// If we get here, the expected exception was not returned
assertTrue("Failed: PageNotFoundException not properly thrown", false);
}
@Test
public void testH_PinPageNotInMemoryWithReplacement() {
try {
first_pid = Minibase.BufferManager.newPage(pg, numPages + 1);
} catch (DiskMgrException e) {
assertTrue("Unexpected Failure: error with DiskMgr for initial allocation", false);
} catch (BufferPoolExceededException e) {
assertTrue("Unexpected Failure: Buffer Pool Full for initial allocation", false);
}
try {
Minibase.BufferManager.unpinPage(first_pid, false);
} catch (PageNotFoundException e) {
assertTrue("Unexpected Failure: page not found in hash table when unpinning", false);
} catch (PageUnpinnedException e) {
assertTrue("Unexpected Failure: page already unpinned", false);
}
// Pin and unpin enough pages to fill buffer
for (pid.pid = first_pid.pid, last_pid.pid = pid.pid + numPages; pid.pid < last_pid.pid; pid.pid = pid.pid
+ 1) {
try {
Minibase.BufferManager.pinPage(pid, pg, false);
} catch (BufferPoolExceededException e) {
assertTrue("Unexpected Failure: BufferPoolExceeded exception thrown for page " + pid.pid, false);
} catch (DiskMgrException e) {
assertTrue("Unexpected Failure: exception at disk manager for pinning page " + pid.pid, false);
}
try {
Minibase.BufferManager.unpinPage(pid, false);
} catch (PageNotFoundException e) {
assertTrue("Unexpected Failure: page " + pid.pid + " not found in hash table", false);
} catch (PageUnpinnedException e) {
assertTrue("Unexpected Failure: page " + pid.pid + " already unpinned", false);
}
}
// Now attempt to bring another page into memory
try {
Minibase.BufferManager.pinPage(last_pid, pg, false);
} catch (BufferPoolExceededException e) {
assertTrue("Unexpected Failure: BufferPoolExceeded exception thrown for last page " + last_pid.pid, false);
} catch (DiskMgrException e) {
assertTrue("Unexpected Failure: exception at disk manager when performing replacement", false);
}
// Pinned a page using replacement policy - verify that FD is correct
Integer fnum = Minibase.BufferManager.getFrameFromPage(last_pid);
if (fnum == null)
assertTrue("Failed: page not in hash table", false);
pg = Minibase.BufferManager.getPageFromFrame(fnum);
if (pg == null)
assertTrue("Failed: page not in frame", false);
FrameDescriptor fd = Minibase.BufferManager.getFrameDesc(fnum);
checkFDContents(fd, last_pid.pid, 1, false);
}
@Test
public void testI_PinPageReplaceDirtyPage() {
try {
first_pid = Minibase.BufferManager.newPage(pg, numPages + 1);
} catch (DiskMgrException e) {
assertTrue("Unexpected Failure: error with DiskMgr for initial allocation", false);
} catch (BufferPoolExceededException e) {
assertTrue("Unexpected Failure: Buffer Pool Full for initial allocation", false);
}
try {
Minibase.BufferManager.unpinPage(first_pid, false);
} catch (PageNotFoundException e) {
assertTrue("Unexpected Failure: page not found in hash table when unpinning", false);
} catch (PageUnpinnedException e) {
assertTrue("Unexpected Failure: page already unpinned", false);
}
// Pin and unpin enough pages to fill buffer
for (pid.pid = first_pid.pid, last_pid.pid = pid.pid + numPages; pid.pid < last_pid.pid; pid.pid = pid.pid
+ 1) {
try {
Minibase.BufferManager.pinPage(pid, pg, false);
// Write some data to each page
int data = pid.pid + 99999;
Convert.setIntValue(data, 0, pg.getpage());
} catch (BufferPoolExceededException e) {
assertTrue("Unexpected Failure: BufferPoolExceeded exception thrown for page " + pid.pid, false);
} catch (DiskMgrException e) {
assertTrue("Unexpected Failure: exception at disk manager for page " + pid.pid, false);
} catch (IOException e) {
assertTrue("Unexpected Failure: could not write page data for page " + pid.pid, false);
}
// Unpin page - it's dirty
try {
Minibase.BufferManager.unpinPage(pid, true);
} catch (PageNotFoundException e) {
assertTrue("Unexpected Failure: page " + pid.pid + " not found in hash table", false);
} catch (PageUnpinnedException e) {
assertTrue("Unexpected Failure: page " + pid.pid + " already unpinned", false);
}
}
// Now attempt to bring another page into memory, then unpin it
pid.pid = last_pid.pid + 1;
try {
Minibase.BufferManager.pinPage(pid, pg, false);
} catch (BufferPoolExceededException e) {
assertTrue("Unexpected Failure: BufferPoolExceeded exception thrown for last page " + last_pid.pid + 1
+ " during replacement", false);
} catch (DiskMgrException e) {
assertTrue("Unexpected Failure: exception at disk manager when performing replacement", false);
}
// Pinned a page using replacement policy - FIFO should remove page with
// pid=first_pid
// Verify that page data in frame is overwritten
try {
Integer fnum = Minibase.BufferManager.getFrameFromPage(pid);
if (fnum == null)
assertTrue("Failed: page " + pid.pid + " not in hash table after replacement", false);
pg = Minibase.BufferManager.getPageFromFrame(fnum);
if (pg == null)
assertTrue("Failed: page " + pid.pid + " not in frame after replacement", false);
pg = Minibase.BufferManager.getPageFromFrame(fnum);
int data = Convert.getIntValue(0, pg.getpage());
if (data == first_pid.pid + 99999)
assertTrue("Failure: page stored in frame not overwritten when replaced", false);
} catch (IOException e) {
assertTrue("Unexpected Failure: reading from page " + pid.pid, false);
}
try {
Minibase.BufferManager.unpinPage(pid, true);
} catch (PageNotFoundException e) {
assertTrue("Unexpected Failure: page " + pid.pid + " not found in hash table", false);
} catch (PageUnpinnedException e) {
assertTrue("Unexpected Failure: page " + pid.pid + " already unpinned", false);
}
// Bring in page with pid=first_pid again and see if its data is retrieved
try {
Minibase.BufferManager.pinPage(first_pid, pg, false);
} catch (BufferPoolExceededException e) {
assertTrue("Unexpected Failure: BufferPoolExceeded bringing first page in from memory " + first_pid.pid
+ " during replacement", false);
} catch (DiskMgrException e) {
assertTrue("Unexpected Failure: exception at disk manager bringing first page in from memory", false);
}
// Verify contents of page after bringing back from disk
try {
Integer fnum = Minibase.BufferManager.getFrameFromPage(first_pid);
if (fnum == null)
assertTrue("Failed: page " + first_pid.pid + " not in hash table after replacement", false);
pg = Minibase.BufferManager.getPageFromFrame(fnum);
if (pg == null)
assertTrue("Failed: page " + first_pid.pid + " not in frame after replacement", false);
pg = Minibase.BufferManager.getPageFromFrame(fnum);
int data = Convert.getIntValue(0, pg.getpage());
// Finally, check page
assertTrue("Failure: page stored in frame not overwritten when replaced", data == first_pid.pid + 99999);
} catch (IOException e) {
assertTrue("Unexpected Failure: reading from page " + first_pid.pid, false);
}
}
@Test
public void testJ_FIFOBehavior() {
try {
first_pid = Minibase.BufferManager.newPage(pg, numPages + 1);
} catch (DiskMgrException e) {
assertTrue("Unexpected Failure: error with DiskMgr for initial allocation", false);
} catch (BufferPoolExceededException e) {
assertTrue("Unexpected Failure: Buffer Pool Full for initial allocation", false);
}
try {
Minibase.BufferManager.unpinPage(first_pid, false);
} catch (PageNotFoundException e) {
assertTrue("Unexpected Failure: page not found in hash table when unpinning", false);
} catch (PageUnpinnedException e) {
assertTrue("Unexpected Failure: page already unpinned", false);
}
// Pin enough pages to fill buffer
for (pid.pid = first_pid.pid, last_pid.pid = pid.pid + numPages; pid.pid < last_pid.pid; pid.pid = pid.pid + 1) {
try {
Minibase.BufferManager.pinPage(pid, pg, false);
// Write some data to each page
int data = pid.pid + 99999;
Convert.setIntValue(data, 0, pg.getpage());
} catch (BufferPoolExceededException e) {
assertTrue("Unexpected Failure: BufferPoolExceeded exception thrown for page " + pid.pid, false);
} catch (DiskMgrException e) {
assertTrue("Unexpected Failure: exception at disk manager for page " + pid.pid, false);
} catch (IOException e) {
assertTrue("Unexpected Failure: cannot write data for page " + pid.pid, false);
}
}
// Pick three pages to unpin. Store the frames for reference later
PageId pg1 = new PageId(), pg2 = new PageId(), pg3 = new PageId();
int pageRange = last_pid.pid - first_pid.pid;
pg1.pid = first_pid.pid + (pageRange / 3);
Integer f1 = Minibase.BufferManager.getFrameFromPage(pg1);
pg2.pid = first_pid.pid + (pageRange / 3) * 2;
Integer f2 = Minibase.BufferManager.getFrameFromPage(pg2);
pg3.pid = first_pid.pid + pageRange-1;
Integer f3 = Minibase.BufferManager.getFrameFromPage(pg3);
// Unpin pages in order: pg2, pg1, pg3. FIFO should then select pg3 to evict
try {
Minibase.BufferManager.unpinPage(pg2, true);
} catch (PageNotFoundException e) {
assertTrue("Unexpected Failure: replacement page " + pg2.pid + " not found in hash table", false);
} catch (PageUnpinnedException e) {
assertTrue("Unexpected Failure: replacement page " + pg2.pid + " already unpinned", false);
}
try {
Minibase.BufferManager.unpinPage(pg1, true);
} catch (PageNotFoundException e) {
assertTrue("Unexpected Failure: replacement page " + pg1.pid + " not found in hash table", false);
} catch (PageUnpinnedException e) {
assertTrue("Unexpected Failure: replacement page " + pg1.pid + " already unpinned", false);
}
try {
Minibase.BufferManager.unpinPage(pg3, true);
} catch (PageNotFoundException e) {
assertTrue("Unexpected Failure: replacement page " + pg3.pid + " not found in hash table", false);
} catch (PageUnpinnedException e) {
assertTrue("Unexpected Failure: replacement page " + pg3.pid + " already unpinned", false);
}
// Now attempt to bring another page into memory
pid.pid = last_pid.pid + 1;
try {
Minibase.BufferManager.pinPage(pid, pg, false);
} catch (BufferPoolExceededException e) {
assertTrue("Unexpected Failure: BufferPoolExceeded exception thrown for last page " + last_pid.pid + 1
+ " during replacement", false);
} catch (DiskMgrException e) {
assertTrue("Unexpected Failure: exception at disk manager during replacement", false);
}
// Pinned a page using replacement policy - FIFO should remove page with pid=pg2
// Verify that page data in frame is overwritten
try {
Integer fnum = Minibase.BufferManager.getFrameFromPage(pid);
if (fnum == null)
assertTrue("Failed: page " + pid.pid + " not in hash table after replacement", false);
pg = Minibase.BufferManager.getPageFromFrame(fnum);
if (pg == null)
assertTrue("Failed: page " + pid.pid + " not in frame after replacement", false);
pg = Minibase.BufferManager.getPageFromFrame(fnum);
int data = Convert.getIntValue(0, pg.getpage());
if (data == pg2.pid + 99999)
assertTrue("Failure: page stored in frame not overwritten when replaced", false);
// Now that replacement policy has been used, verify we actually evicted pg3
assertTrue("Failed: wrong page evicted, should be page " + pg2.pid + " in frame " + f2, fnum == f2);
} catch (IOException e) {
assertTrue("Unexpected Failure: reading from page " + pid.pid, false);
}
}
@Test
public void testK_BufferFull() {
try {
first_pid = Minibase.BufferManager.newPage(pg, numPages + 1);
} catch (DiskMgrException e) {
assertTrue("Unexpected Failure: error with DiskMgr for initial allocation", false);
} catch (BufferPoolExceededException e) {
assertTrue("Unexpected Failure: Buffer Pool Full for initial allocation", false);
}
try {
Minibase.BufferManager.unpinPage(first_pid, false);
} catch (PageNotFoundException e) {
assertTrue("Unexpected Failure: page not found in hash table", false);
} catch (PageUnpinnedException e) {
assertTrue("Unexpected Failure: page already unpinned", false);
}
// Pin enough pages to fill buffer
for (pid.pid = first_pid.pid, last_pid.pid = pid.pid + numPages; pid.pid < last_pid.pid; pid.pid = pid.pid
+ 1) {
try {
Minibase.BufferManager.pinPage(pid, pg, false);
// Write some data to each page
int data = pid.pid + 99999;
Convert.setIntValue(data, 0, pg.getpage());
} catch (BufferPoolExceededException e) {
assertTrue("Unexpected Failure: BufferPoolExceeded exception thrown for page " + pid.pid, false);
} catch (DiskMgrException e) {
assertTrue("Unexpected Failure: exception at disk manager for page " + pid.pid, false);
} catch (IOException e) {
assertTrue("Unexpected Failure: cannot write to page " + pid.pid, false);
}
}
// Now attempt to bring another page into memory, it should fail
pid.pid = last_pid.pid + 1;
try {
Minibase.BufferManager.pinPage(pid, pg, false);
} catch (BufferPoolExceededException bpe_ex) {
assertTrue(true);
} catch (DiskMgrException e) {
assertTrue("Unexpected Failure: exception at disk manager for page " + pid.pid, false);
}
// If we reach here, expected exception was not thrown
assertTrue("Failure: expected BufferPoolExceeded exception not thrown thrown for page " + pid.pid, true);
}
@Test
public void testL_NewPageDeallocation()
{
//Allocate enough pages to fill the buffer
int numTestPages = numPages - 3; //-3 here is to account for required DiskMgr pages, which we will force to be pinned for this test
try {
first_pid = Minibase.BufferManager.newPage(pg, numTestPages);
} catch (DiskMgrException e) {
assertTrue("Unexpected Failure: error with DiskMgr for initial allocation", false);
} catch (BufferPoolExceededException e) {
assertTrue("Unexpected Failure: Buffer Pool Full for initial allocation", false);
}
//Force all required DiskMgr pages to be pinned
for(pid.pid = 0; pid.pid < first_pid.pid; pid.pid = pid.pid + 1)
{
try {
Minibase.BufferManager.pinPage(pid, pg, false);
} catch (BufferPoolExceededException e) {
assertTrue("Unexpected Failure: BufferPoolExceeded exception thrown for DiskMgr page " + pid.pid, false);
} catch (DiskMgrException e) {
assertTrue("Unexpected Failure: exception at disk manager for DiskMgr page " + pid.pid, false);
}
}
// Pin enough pages to fill buffer
for (pid.pid = first_pid.pid+1, last_pid.pid = first_pid.pid + numTestPages; pid.pid < last_pid.pid; pid.pid = pid.pid
+ 1) {
try {
Minibase.BufferManager.pinPage(pid, pg, false);
} catch (BufferPoolExceededException e) {
assertTrue("Unexpected Failure: BufferPoolExceeded exception thrown for page " + pid.pid, false);
} catch (DiskMgrException e) {
assertTrue("Unexpected Failure: exception at disk manager for page " + pid.pid, false);
}
}
//Allocate enough pages to completely fill the database. However, we expect pinning the page to fail here
boolean pin = true;
try {
pid = Minibase.BufferManager.newPage(pg, DB_SIZE - last_pid.pid);
} catch (DiskMgrException e) {
e.printStackTrace();
assertTrue("Unexpected Failure: error with DiskMgr for allocation that fills the DB", false);
} catch (BufferPoolExceededException e) {
//Set a flag to show this exception was thrown successfully
pin = false;
}
if(pin)
assertTrue("Unexpected Failure: Page allocation with full buffer did not throw BufferPoolExceededException", false);
//Unpin all pages
for (pid.pid = 0; pid.pid < last_pid.pid; pid.pid = pid.pid + 1) {
try {
Minibase.BufferManager.unpinPage(pid, false);
} catch (PageNotFoundException e) {
assertTrue("Unexpected Failure: page " + pid.pid + " not found in hash table", false);
} catch (PageUnpinnedException e) {
assertTrue("Unexpected Failure: page " + pid.pid + " already unpinned", false);
}
}
//Allocate new pages again - this should succeed now that the buffer is unpinned
try {
pid = Minibase.BufferManager.newPage(pg, DB_SIZE - last_pid.pid);
} catch (OutOfSpaceException e) {
assertTrue("Failure: disk pages not deallocated after failure to pin them", false);
} catch (DiskMgrException e) {
assertTrue("Unexpected Failure: error with DiskMgr for allocation that fills the DB", false);
} catch (BufferPoolExceededException e) {
assertTrue("Unexpected Failure: buffer pool full when trying to allocate new pages", false);
}
//If we get here, then we have succeeded
assertTrue(true);
}
@Test //This is a simple test to demonstrate Freepage method. We create a new empty page, bring it to memory queue but do NOT pin it. It should be able to safely free the page.
public void testM_FreeAnEmptyPage()
{
try {
first_pid = Minibase.BufferManager.newPage(pg, 1);
} catch (DiskMgrException e) {
assertTrue("Unexpected Failure: error with DiskMgr for initial allocation", false);
} catch (BufferPoolExceededException e) {
assertTrue("Unexpected Failure: Buffer Pool Full for initial allocation", false);
}
try {
Minibase.BufferManager.freePage(first_pid);
//assertTrue("freepage success", true);
} catch (PagePinnedException e) {
assertTrue("Test Failed: Page pinned already", true);
//System.out.println(" --> Failed as expected \n");
//status = FAIL; // what we want
} catch (Exception e) {
e.printStackTrace();
}
}
@Test //This test first creates a new emopty page, pins it and tries to Free it but as it is pinned already, we expect it to fail.
public void testN_FreeAPinnedPage(){
try {
first_pid = Minibase.BufferManager.newPage(pg, 1);
} catch (DiskMgrException e) {
assertTrue("Unexpected Failure: error with DiskMgr for initial allocation", false);
} catch (BufferPoolExceededException e) {
assertTrue("Unexpected Failure: Buffer Pool Full for initial allocation", false);
}
try {
Minibase.BufferManager.pinPage(first_pid, pg, false);
} catch (BufferPoolExceededException e) {
assertTrue("Unexpected Failure: Buffer Pool Full for repinning already pinned page", false);
} catch (DiskMgrException e) {
assertTrue("Unexpected Failure: error with DiskMgr pinning pinned page", false);
}
try {
Minibase.BufferManager.freePage(first_pid);
assertTrue("Unexpected behavior: Freepage was a success even though page was pinned", false);
} catch (PagePinnedException e) {
assertTrue("Test Success i.e. Failed as expected: Page pinned already - so Freepage will not suceed. This is the expected behavior.", true);
} catch (Exception e) {
e.printStackTrace();
}
}
@Test
public void testO_FreePageOnWrittenPages() {
try {
first_pid = Minibase.BufferManager.newPage(pg, numPages + 1);
} catch (DiskMgrException e) {
assertTrue("Unexpected Failure: error with DiskMgr for initial allocation", false);
} catch (BufferPoolExceededException e) {
assertTrue("Unexpected Failure: Buffer Pool Full for initial allocation", false);
}
try {
Minibase.BufferManager.unpinPage(first_pid, false);
} catch (PageNotFoundException e) {
assertTrue("Unexpected Failure: page not found in hash table when unpinning", false);
} catch (PageUnpinnedException e) {
assertTrue("Unexpected Failure: page already unpinned", false);
}
// Pin enough pages to fill buffer
for (pid.pid = first_pid.pid, last_pid.pid = pid.pid + numPages; pid.pid < last_pid.pid; pid.pid = pid.pid + 1) {
try {
Minibase.BufferManager.pinPage(pid, pg, false);
// Write some data to each page
int data = pid.pid + 99999;
Convert.setIntValue(data, 0, pg.getpage());
} catch (BufferPoolExceededException e) {
assertTrue("Unexpected Failure: BufferPoolExceeded exception thrown for page " + pid.pid, false);
} catch (DiskMgrException e) {
assertTrue("Unexpected Failure: exception at disk manager for page " + pid.pid, false);
} catch (IOException e) {
assertTrue("Unexpected Failure: cannot write data for page " + pid.pid, false);
}
}
// Pick three pages to unpin. But unpin only two and keep the third pinned
PageId pg1 = new PageId(), pg2 = new PageId(), pg3 = new PageId();
int pageRange = last_pid.pid - first_pid.pid;
pg1.pid = first_pid.pid + (pageRange / 3);
Integer f1 = Minibase.BufferManager.getFrameFromPage(pg1);
pg2.pid = first_pid.pid + (pageRange / 3) * 2;
Integer f2 = Minibase.BufferManager.getFrameFromPage(pg2);
pg3.pid = first_pid.pid + pageRange-1;
Integer f3 = Minibase.BufferManager.getFrameFromPage(pg3);
// Unpin pages in order: pg2, pg1, pg3 (as should be in FIFO policy). But for the test we do not unpin pg3
try {
Minibase.BufferManager.unpinPage(pg2, true);
} catch (PageNotFoundException e) {
assertTrue("Unexpected Failure: replacement page " + pg2.pid + " not found in hash table", false);
} catch (PageUnpinnedException e) {
assertTrue("Unexpected Failure: replacement page " + pg2.pid + " already unpinned", false);
}
try {
Minibase.BufferManager.unpinPage(pg1, true);
} catch (PageNotFoundException e) {
assertTrue("Unexpected Failure: replacement page " + pg1.pid + " not found in hash table", false);
} catch (PageUnpinnedException e) {
assertTrue("Unexpected Failure: replacement page " + pg1.pid + " already unpinned", false);
}
try {
Minibase.BufferManager.freePage(pg1);
assertTrue("Tests passed: PG1 was unpinned and should be able to be freed", true);
} catch (PagePinnedException e) {
assertTrue("Test Failed i.e. should be able to free an empty page", false);
} catch (Exception e) {
e.printStackTrace();
}
try {
Minibase.BufferManager.freePage(pg3);
assertTrue("Tests failed: PG3 was pinned (and written) and should NOT be able to be freed", false);
} catch (PagePinnedException e) {
assertTrue("Test passed i.e. should not be able to free a pinned page that was written on", true);
} catch (Exception e) {
e.printStackTrace();
}
}
}
@@ -0,0 +1,17 @@
package tests;
import org.junit.runner.JUnitCore;
import org.junit.runner.Result;
import org.junit.runner.notification.Failure;
public class TestDriver {
public static void main(String[] args) {
Result result = JUnitCore.runClasses(tests.BMTest.class);
for (Failure failure : result.getFailures()) {
System.out.println(failure.toString());
}
System.out.println(result.wasSuccessful());
}
}
+23
View File
@@ -0,0 +1,23 @@
bin/
.DS_Store
sean.minibase
# ---> Maven
target/
pom.xml.tag
pom.xml.releaseBackup
pom.xml.versionsBackup
pom.xml.next
release.properties
dependency-reduced-pom.xml
buildNumber.properties
.mvn/timing.properties
# https://github.com/takari/maven-wrapper#usage-without-binary-jar
.mvn/wrapper/maven-wrapper.jar
# Eclipse m2e generated files
# Eclipse Core
.project
# JDT-specific (Eclipse Java Development Tools)
.classpath
+135
View File
@@ -0,0 +1,135 @@
Test Case 1 (Handout example)
Log:
W:0,T1,1,1,5,-1
R:1,T1,2,2,0
W:2,T1,2,2,3,1
R:3,T1,1,5,2
C:4,T1,3
R:5,T2,1,5,-1
W:6,T2,1,5,2,5
C:7,T2,6
Test Case 2 (Three transactions)
Log:
R:0,T1,6,6,-1
R:1,T2,4,4,-1
R:2,T3,9,9,-1
W:3,T1,7,7,2,0
W:4,T2,2,2,4,1
R:5,T3,6,6,2
W:6,T1,5,5,8,3
W:7,T3,1,1,9,5
C:8,T3,7
W:9,T1,6,6,2,6
C:10,T1,9
R:11,T2,5,8,4
W:12,T2,7,2,3,11
C:13,T2,12
Test Case 3 (Deadlocks)
Log:
W:0,T1,4,4,1,-1
W:1,T2,5,5,2,-1
W:2,T3,6,6,3,-1
R:3,T1,1,1,0
R:4,T2,1,1,1
R:5,T3,2,2,2
R:6,T2,2,2,4
A:7,T3,5
W:8,T2,2,2,3,6
C:9,T2,8
W:10,T1,1,1,2,3
C:11,T1,10
Test Case 4 (No Conflicts)
Log:
R:0,T1,1,1,-1
R:1,T2,1,1,-1
R:2,T1,2,2,0
R:3,T2,2,2,1
R:4,T1,3,3,2
R:5,T2,3,3,3
W:6,T1,4,4,1,4
W:7,T2,5,5,2,5
C:8,T1,6
C:9,T2,7
Test Case 5: Multiple Deadlocks OR if deadlock detection finds T1 & T2 deadlock first:
Log: Log:
R:0,T1,1,1,-1 R:0,T1,1,1,-1
R:1,T2,2,2,-1 R:1,T2,2,2,-1
R:2,T3,1,1,-1 R:2,T3,1,1,-1
R:3,T2,3,3,1 R:3,T2,3,3,1
A:4,T3,2 A:4,T2,3
A:5,T2,3 W:5,T3,3,3,4,2
W:6,T1,2,2,1,0 W:6,T1,2,2,1,0
C:7,T1,6 C:7,T3,5
C:8,T1,6
Test Case 6: Larger deadlock cycle
Log:
R:0,T1,1,1,-1
R:1,T2,2,2,-1
R:2,T3,3,3,-1
R:3,T4,4,4,-1
A:4,T4,3
W:5,T3,4,4,3,2
C:6,T3,5
W:7,T2,3,3,2,1
C:8,T2,7
W:9,T1,2,2,1,0
C:10,T1,9
Test Case 7: Small deadlock cycle
Log:
W:0,T1,1,1,2,-1
W:1,T2,2,2,5,-1
A:2,T2,1
R:3,T1,2,2,0
C:4,T1,3
Test Case 8: Three transaction with deadlock cycle
Log:
R:0,T1,6,6,-1
R:1,T2,4,4,-1
R:2,T3,9,9,-1
W:3,T1,7,7,2,0
W:4,T2,2,2,4,1
R:5,T3,6,6,2
R:6,T2,5,5,4
W:7,T3,1,1,9,5
A:8,T2,6
C:9,T3,7
W:10,T1,2,2,8,3
W:11,T1,6,6,2,10
C:12,T1,11
Test Case 9: Small transactions without deadlock cycle
Log:
W:0,T1,1,1,2,-1
W:1,T2,3,3,5,-1
R:2,T1,2,2,0
R:3,T2,4,4,1
C:4,T1,2
C:5,T2,3
Test Case 10: Handout example with Deadlock
Log:
W:0,T1,1,1,5,-1
R:1,T2,2,2,-1
R:2,T1,2,2,0
A:3,T2,1
W:4,T1,2,2,3,2
R:5,T1,1,5,4
C:6,T1,5
Binary file not shown.
+92
View File
@@ -0,0 +1,92 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>edu.cs.purdue</groupId>
<artifactId>cs448p4</artifactId>
<version>1.0-SNAPSHOT</version>
<name>cs448p4</name>
<url>https://www.cs.purdue.edu/homes/bb/cs448f19/</url>
<properties>
<java.version>10</java.version>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.source>${java.version}</maven.compiler.source>
<maven.compiler.target>${java.version}</maven.compiler.target>
</properties>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.11</version>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<pluginManagement><!-- lock down plugins versions to avoid using Maven defaults (may be moved to parent pom) -->
<plugins>
<!-- clean lifecycle, see https://maven.apache.org/ref/current/maven-core/lifecycles.html#clean_Lifecycle -->
<plugin>
<artifactId>maven-clean-plugin</artifactId>
<version>3.1.0</version>
</plugin>
<!-- default lifecycle, jar packaging: see https://maven.apache.org/ref/current/maven-core/default-bindings.html#Plugin_bindings_for_jar_packaging -->
<plugin>
<artifactId>maven-resources-plugin</artifactId>
<version>3.0.2</version>
</plugin>
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.8.0</version>
<configuration>
<release>${java.version}</release>
</configuration>
</plugin>
<plugin>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.22.1</version>
</plugin>
<plugin>
<artifactId>maven-jar-plugin</artifactId>
<version>3.0.2</version>
</plugin>
<plugin>
<artifactId>maven-install-plugin</artifactId>
<version>2.5.2</version>
</plugin>
<plugin>
<artifactId>maven-deploy-plugin</artifactId>
<version>2.8.2</version>
</plugin>
<!-- site lifecycle, see https://maven.apache.org/ref/current/maven-core/lifecycles.html#site_Lifecycle -->
<plugin>
<artifactId>maven-site-plugin</artifactId>
<version>3.7.1</version>
</plugin>
<plugin>
<artifactId>maven-project-info-reports-plugin</artifactId>
<version>3.0.0</version>
</plugin>
<plugin>
<artifactId>maven-assembly-plugin</artifactId>
<configuration>
<archive>
<manifest>
<!--add test cases file in here -->
<mainClass>test.TestDriver</mainClass>
</manifest>
</archive>
<descriptorRefs>
<descriptorRef>jar-with-dependencies</descriptorRef>
</descriptorRefs>
</configuration>
</plugin>
</plugins>
</pluginManagement>
</build>
</project>
+418
View File
@@ -0,0 +1,418 @@
package CC;
import java.util.List;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.Queue;
enum LockState {
NONE,
SHARED,
EXCLUSIVE
}
class Lock {
private ArrayList<Integer> transactionIds;
private LockState type;
private int noReads;
public Lock() {
this.transactionIds = new ArrayList<Integer>();
this.noReads = 0;
this.type = LockState.NONE;
}
public ArrayList<Integer> getTransactionIds() {
return transactionIds;
}
public void addTransactionId(int transactionId) {
if (!transactionIds.contains(Integer.valueOf(transactionId))) {
transactionIds.add(transactionId);
noReads++;
}
}
public LockState getType() {
return type;
}
public void setType(LockState type) {
this.type = type;
}
public int getNoReads() {
return noReads;
}
public boolean hasLock(int transactionId) {
return transactionIds.contains(Integer.valueOf(transactionId));
}
public void release(int releaseTransactionId) {
transactionIds.remove(Integer.valueOf(releaseTransactionId));
noReads--;
if (noReads == 0) {
this.type = LockState.NONE;
}
}
}
class LockTable {
private Lock[] locks;
private static final int NUM_RECORDS = 10;
public LockTable() {
this.locks = new Lock[NUM_RECORDS];
// initialize the locktable
for (int recordId = 0; recordId < NUM_RECORDS; recordId++) {
locks[recordId] = new Lock();
}
}
public Lock getLock(int recordId) {
if (recordId >= 0 && recordId < locks.length) {
return locks[recordId];
} else {
throw new IllegalArgumentException("Invalid recordId: " + recordId);
}
}
public void releaseLocksForTransaction(int[] recordIds, int transactionId) {
for (int recordId : recordIds) {
if (recordId >= 0 && recordId < locks.length) {
locks[recordId].release(transactionId);
} else {
throw new IllegalArgumentException("Invalid recordId: " + recordId);
}
}
}
}
interface Operation {
int getRecordId();
int getValue();
}
class WriteOp implements Operation {
private int recordId;
private int value;
public WriteOp(int recordId, int value) {
this.recordId = recordId;
this.value = value;
}
public int getRecordId() {
return recordId;
}
public int getValue() {
return value;
}
}
class ReadOp implements Operation {
private int recordId;
public ReadOp(int recordId) {
this.recordId = recordId;
}
public int getRecordId() {
return recordId;
}
public int getValue() {
return -1;
}
}
class CommitOp implements Operation {
public int getRecordId() {
return -1;
}
public int getValue() {
return -1;
}
}
class Transaction {
private int currentOperationIndex;
private Operation[] operations;
private int transactionId;
private ArrayList<Integer> recordLocks;
private int prevTimestamp;
private boolean aborted;
public Transaction(String[] operations, int transactionId) {
this.currentOperationIndex = 0;
this.operations = new Operation[operations.length];
this.transactionId = transactionId;
this.recordLocks = new ArrayList<Integer>();
this.prevTimestamp = -1;
this.aborted = false;
int OpIndex = 0;
for (String operation : operations) {
if (operation.charAt(0) == 'W') {
this.operations[OpIndex] = new WriteOp(Character.getNumericValue(operation.charAt(2)),
Character.getNumericValue(operation.charAt(4)));
} else if (operation.charAt(0) == 'R') {
this.operations[OpIndex] = new ReadOp(Character.getNumericValue(operation.charAt(2)));
} else {
this.operations[OpIndex] = new CommitOp();
}
OpIndex++;
}
}
public int getCurrentOperationIndex() {
return currentOperationIndex;
}
public int getTransactionId() {
return transactionId;
}
public void setCurrentOperationIndex(int currentOperationIndex) {
this.currentOperationIndex = currentOperationIndex;
}
public Operation[] getOperations() {
return operations;
}
public boolean hasNextOperation() {
return (currentOperationIndex < operations.length) && !aborted;
}
public int doNextOperation(LockTable lockTable, int[] database, ArrayList<String[]> systemLog, int timestamp,
LinkedList<Integer>[] adj) {
if (hasNextOperation() && !aborted) {
Operation nextOp = operations[currentOperationIndex];
Lock nextLock = null;
if (!(nextOp instanceof CommitOp)) {
nextLock = lockTable.getLock(nextOp.getRecordId());
}
currentOperationIndex++;
if (nextOp instanceof ReadOp) {
if (!(nextLock.hasLock(transactionId))) {
// The current transaction doesn't already have the lock.
if (nextLock.getType() == LockState.EXCLUSIVE) {
currentOperationIndex--;
for (int adjTransactionId : nextLock.getTransactionIds()) {
if (adjTransactionId != transactionId
&& !adj[transactionId].contains(Integer.valueOf(adjTransactionId))) {
adj[transactionId].add(adjTransactionId);
}
}
return timestamp;
// The lock on the record is exclusive.
} else {
nextLock.setType(LockState.SHARED);
nextLock.addTransactionId(transactionId);
recordLocks.add(nextOp.getRecordId());
}
}
String[] log = { "R", Integer.toString(timestamp), "T" + Integer.toString(transactionId),
Integer.toString(nextOp.getRecordId()), Integer.toString(database[nextOp.getRecordId()]),
Integer.toString(prevTimestamp) };
systemLog.add(log);
} else if (nextOp instanceof WriteOp) {
int prevValue = database[nextOp.getRecordId()];
if ((nextLock.hasLock(transactionId) && nextLock.getNoReads() == 1)
|| nextLock.getType() == LockState.NONE) {
nextLock.setType(LockState.EXCLUSIVE);
database[nextOp.getRecordId()] = nextOp.getValue();
nextLock.addTransactionId(transactionId);
if (!recordLocks.contains(Integer.valueOf(nextOp.getRecordId()))) {
recordLocks.add(nextOp.getRecordId());
}
} else {
currentOperationIndex--;
for (int adjTransactionId : nextLock.getTransactionIds()) {
if (adjTransactionId != transactionId
&& !adj[transactionId].contains(Integer.valueOf(adjTransactionId))) {
adj[transactionId].add(adjTransactionId);
}
}
return timestamp;
}
String[] log = { "W", Integer.toString(timestamp), "T" + Integer.toString(transactionId),
Integer.toString(nextOp.getRecordId()), Integer.toString(prevValue),
Integer.toString(database[nextOp.getRecordId()]),
Integer.toString(prevTimestamp) };
systemLog.add(log);
} else {
for (int recordLock : recordLocks) {
lockTable.getLock(recordLock).release(transactionId);
}
recordLocks = new ArrayList<Integer>();
String[] log = { "C", Integer.toString(timestamp), "T" + Integer.toString(transactionId),
Integer.toString(prevTimestamp) };
systemLog.add(log);
}
prevTimestamp = timestamp;
timestamp++;
}
return timestamp;
}
public void reset() {
currentOperationIndex = 0;
recordLocks = new ArrayList<Integer>();
}
public int abortTransaction(LockTable lockTable, int[] database, ArrayList<String[]> systemLog, int timestamp,
LinkedList<Integer>[] adj) {
aborted = true;
int pastTransaction = prevTimestamp;
do {
String[] lastLog = systemLog.get(pastTransaction);
if (lastLog[0] == "W") {
database[Integer.parseInt(lastLog[3])] = Integer.parseInt(lastLog[4]);
}
pastTransaction = Integer.parseInt(lastLog[lastLog.length - 1]);
} while (pastTransaction != -1);
for (int recordLock : recordLocks) {
lockTable.getLock(recordLock).release(transactionId);
}
recordLocks = new ArrayList<Integer>();
adj[transactionId] = new LinkedList<Integer>();
String[] log = { "A", Integer.toString(timestamp), "T" + Integer.toString(transactionId),
Integer.toString(prevTimestamp) };
systemLog.add(log);
return -1;
}
}
public class CC {
private static final int NUM_RECORDS = 10;
/**
* Notes:
* - Execute all given transactions, using locking.
* - Each element in the transactions List represents all operations performed
* by one transaction, in order.
* - No operation in a transaction can be executed out of order, but operations
* may be interleaved with other
* transactions if allowed by the locking.
* - The index of the transaction in the list is equivalent to the transaction
* ID.
* - Print the log to the console at the end of the method.
* - Return the new db state after executing the transactions.
*
* @param db the initial status of the db
* @param transactions the schedule, which basically is a {@link List} of
* transactions.
* @return the final status of the db
*/
public static int[] executeSchedule(int[] db, List<String> transactions) {
LockTable lockTable = new LockTable();
Queue<Transaction> transactionQueue = new LinkedList<>();
Transaction[] transactionsArray = new Transaction[transactions.size() + 1];
int newTransactionId = 1;
int[] database = new int[NUM_RECORDS];
ArrayList<String[]> systemLog = new ArrayList<>();
int timestamp = 0;
LinkedList<Integer>[] adj;
for (int i = 0; i < NUM_RECORDS; i++) {
database[i] = i;
}
for (String transaction : transactions) {
Transaction newTransaction = new Transaction(transaction.split(";"), newTransactionId);
transactionQueue.add(newTransaction);
transactionsArray[newTransactionId] = newTransaction;
newTransactionId++;
}
adj = new LinkedList[transactions.size() + 1];
for (int i = 0; i < transactions.size() + 1; ++i) {
adj[i] = new LinkedList<Integer>();
}
while (!transactionQueue.isEmpty()) {
Transaction curTransaction = transactionQueue.remove();
if (curTransaction.hasNextOperation()) {
timestamp = curTransaction.doNextOperation(lockTable, database, systemLog, timestamp, adj);
// Here is where we check if there are deadlocks. We run DFS.
boolean[] visited = new boolean[transactions.size() + 1];
int[] predecessor = new int[transactions.size() + 1];
ArrayList<Integer> nodesInCycle = DFS(curTransaction.getTransactionId(), visited, adj, predecessor);
if (nodesInCycle != null) {
Collections.sort(nodesInCycle);
transactionsArray[nodesInCycle.get(nodesInCycle.size() - 1)].abortTransaction(lockTable, database,
systemLog, timestamp,
adj);
timestamp++;
}
transactionQueue.add(curTransaction);
}
}
for (String[] log : systemLog) {
StringBuilder sb = new StringBuilder(log[0] + ":" + log[1]);
for (int k = 2; k < log.length; k++) {
sb.append("," + log[k]);
}
System.out.println(sb.toString());
}
System.out.println();
return database;
}
public static ArrayList<Integer> DFS(int v, boolean visited[], LinkedList<Integer> adj[], int predecessor[]) {
visited[v] = true;
Iterator<Integer> i = adj[v].listIterator();
while (i.hasNext()) {
int n = i.next();
if (!visited[n]) {
predecessor[n] = v;
return DFS(n, visited, adj, predecessor);
} else {
return returnNodesInCycle(predecessor, v, n);
}
}
return null;
}
public static ArrayList<Integer> returnNodesInCycle(int[] predecessor, int parent, int start) {
ArrayList<Integer> nodesInCycle = new ArrayList<>();
nodesInCycle.add(parent);
nodesInCycle.add(start);
while (predecessor[start] != parent && predecessor[start] != 0) {
nodesInCycle.add(predecessor[start]);
start = predecessor[start];
}
return nodesInCycle;
}
}
@@ -0,0 +1,52 @@
package CC;
import java.util.Arrays;
import java.util.List;
public class Project
{
public static int[] newDB()
{
return new int[]{0,1,2,3,4,5,6,7,8,9};
}
public static void main(String[] args)
{
//Test Cases
//1) Simple testcase (handout)
List<String> tc1 = Arrays.asList(new String[]{"W(1,5);R(2);W(2,3);R(1);C","R(1);W(1,2);C"});
//2) Three transactions
List<String> tc2 = Arrays.asList(new String[]{"R(6);W(7,2);W(5,8);W(6,2);C","R(4);W(2,4);R(5);W(7,3);C","R(9);R(6);W(1,9);C"});
//3) Deadlocks
List<String> tc3 = Arrays.asList(new String[]{"W(4,1);R(1);W(1,2);C","W(5,2);R(1);R(2);W(2,3);C","W(6,3);R(2);W(2,4);C"});
//4) No conflicts
List<String> tc4 = Arrays.asList(new String[]{"R(1);R(2);R(3);W(4,1);C","R(1);R(2);R(3);W(5,2);C"});
//5) Multiple Deadlocks (handout)
List<String> tc5 = Arrays.asList(new String[]{"R(1);W(2,1);C","R(2);R(3);W(1,2);C","R(1);W(3,4);C"});
//6) Larger Deadlock Cycle
List<String> tc6 = Arrays.asList(new String[]{"R(1);W(2,1);C","R(2);W(3,2);C","R(3);W(4,3);C","R(4);W(1,4);C"});
//7) Small Deadlock Cycle
List<String> tc7 = Arrays.asList(new String[]{"W(1,2);R(2);C","W(2,5);R(1);C"});
//8) Three Transactions Deadlock Cycle
List<String> tc8 = Arrays.asList(new String[]{"R(6);W(7,2);W(2,8);W(6,2);C","R(4);W(2,4);R(5);W(7,3);C","R(9);R(6);W(1,9);C"});
//9) Small Transactions without Deadlock Cycle
List<String> tc9 = Arrays.asList(new String[]{"W(1,2);R(2);C","W(3,5);R(4);C"});
//10) Testcase with Deadlock Cycle
List<String> tc10 = Arrays.asList(new String[]{"W(1,5);R(2);W(2,3);R(1);C","R(2);R(1);W(1,2);C"});
//Consult the ExpectedOutputs.txt for the expected DB state and log
System.out.println("Schedule 1: Handout Test Case:\n\t" + Arrays.toString(CC.executeSchedule(newDB(),tc1)) + "\n");
System.out.println("Schedule 2: Three Transactions Test Case:\n\t" + Arrays.toString(CC.executeSchedule(newDB(),tc2)) + "\n");
System.out.println("Schedule 3: Deadlocks Test Case:\n\t" + Arrays.toString(CC.executeSchedule(newDB(),tc3)) + "\n");
System.out.println("Schedule 4: No Conflicts Test Case:\n\t" + Arrays.toString(CC.executeSchedule(newDB(),tc4)) + "\n");
System.out.println("Schedule 5: Multiple Deadlocks Test Case:\n\t" + Arrays.toString(CC.executeSchedule(newDB(),tc5)) + "\n");
System.out.println("Schedule 6: Larger Deadlock Cycle Test Case:\n\t" + Arrays.toString(CC.executeSchedule(newDB(),tc6)) + "\n");
System.out.println("Schedule 7: Testcase with two transactions and a deadlock\n\t" + Arrays.toString(CC.executeSchedule(newDB(),tc7)) + "\n");
System.out.println("Schedule 8: Testcase with three transactions and a deadlock:\n\t" + Arrays.toString(CC.executeSchedule(newDB(),tc8)) + "\n");
System.out.println("Schedule 9: Testcase with two transactions and no deadlocks:\n\t" + Arrays.toString(CC.executeSchedule(newDB(),tc9)) + "\n");
System.out.println("Schedule 10: Testcase with deadlock between two transactions:\n\t" + Arrays.toString(CC.executeSchedule(newDB(),tc10)) + "\n");
}
}
@@ -0,0 +1,224 @@
package tests;
import static org.junit.Assert.*;
import java.io.IOException;
import CC.*;
import org.junit.After;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.FixMethodOrder;
import org.junit.Test;
import org.junit.runners.MethodSorters;
import java.util.Arrays;
import java.util.List;
@FixMethodOrder(MethodSorters.NAME_ASCENDING)
public class CCTest {
public final static boolean OK = true;
public final static boolean FAIL = false;
public static int[] newDB()
{
return new int[]{0,1,2,3,4,5,6,7,8,9};
}
/**
* Schedule 1. Simple testcase with 2 transactions.
* This testcase is shown in the handout, Part 2.
*/
@Test
public void test_A_Simple()
{
// expected output from the given Schedule
int expectedOutput[] = {0, 2, 3, 3, 4, 5, 6, 7, 8, 9};
// input: T1, T2
List<String> tc1 = Arrays.asList(new String[]{"W(1,5);R(2);W(2,3);R(1);C","R(1);W(1,2);C"});
// Here we are returning the state of the database after executing Schedule 1
int methodOutput[] = CC.executeSchedule(newDB(),tc1);
// Here we are checking whether method output matched with the expected output
// if both match it will pass the test, otherwise it will show an error message
assertArrayEquals("output did not match expected result",expectedOutput, methodOutput);
}
/**
* Schedule 2. Testcase with three transactions and no deadlock.
*/
@Test
public void test_B_ThreeTransactions()
{
int expectedOutput[] = {0, 9, 4, 3, 4, 8, 2, 3, 8, 9};
//Testcases
//2) Three transactions
List<String> tc2 = Arrays.asList(new String[]{"R(6);W(7,2);W(5,8);W(6,2);C","R(4);W(2,4);R(5);W(7,3);C","R(9);R(6);W(1,9);C"});
int methodOutput[] = CC.executeSchedule(newDB(),tc2);
assertArrayEquals("output did not match expected result",expectedOutput, methodOutput);
}
/**
* Schedule 3. Testcase with three transactions and a deadlock.
*/
@Test
public void test_C_Deadlocks()
{
int expectedOutput[] = {0, 2, 3, 3, 1, 2, 6, 7, 8, 9};
//Testcases
//3) Deadlocks
List<String> tc3 = Arrays.asList(new String[]{"W(4,1);R(1);W(1,2);C","W(5,2);R(1);R(2);W(2,3);C","W(6,3);R(2);W(2,4);C"});
int methodOutput[] = CC.executeSchedule(newDB(),tc3);
assertArrayEquals("output did not match expected result",expectedOutput, methodOutput);
}
/**
* Schedule 4. Testcase with multiple deadlocks.
* This testcase is shown in the handout, Part 3 (Deadlock Detection/Handling).
*/
@Test
public void test_D_NoConflicts()
{
int expectedOutput[] = {0, 1, 2, 3, 1, 2, 6, 7, 8, 9};
//Testcases
//4) No conflicts
List<String> tc4 = Arrays.asList(new String[]{"R(1);R(2);R(3);W(4,1);C","R(1);R(2);R(3);W(5,2);C"});
int methodOutput[] = CC.executeSchedule(newDB(),tc4);
assertArrayEquals("output did not match expected result",expectedOutput, methodOutput);
}
/**
* Schedule 5. Testcase with multiple deadlocks.
* This testcase is shown in the handout, Part 3 (Deadlock Detection/Handling).
*/
@Test
public void test_E_MultipleDeadlocks()
{
// In the Schedule 5 there can be two possible outcomes depending of how you handle deadlocks.
int expectedOutput[] = {0, 1, 1, 3, 4, 5, 6, 7, 8, 9};
//Testcases
//5) Multiple Deadlocks
List<String> tc5 = Arrays.asList(new String[]{"R(1);W(2,1);C","R(2);R(3);W(1,2);C","R(1);W(3,4);C"});
int methodOutput[] = CC.executeSchedule(newDB(),tc5);
try{
// if T3 is aborted, and then T2
assertArrayEquals("output did not match expected result",expectedOutput, methodOutput);
}catch (AssertionError e) {
// if we abort T2
int expectedOutput_anth[] = {0, 1, 1, 4, 4, 5, 6, 7, 8, 9};
assertArrayEquals("output did not match expected result",expectedOutput_anth, methodOutput);
}
}
/**
* Schedule 6. Testcase with large number of transactions (4) and a deadlock.
*/
@Test
public void test_F_LargerDeadlock()
{
int expectedOutput[] = {0, 1, 1, 2, 3, 5, 6, 7, 8, 9};
//Testcases
//6) Larger Deadlock Cycle
List<String> tc6 = Arrays.asList(new String[]{"R(1);W(2,1);C","R(2);W(3,2);C","R(3);W(4,3);C","R(4);W(1,4);C"});
int methodOutput[] = CC.executeSchedule(newDB(),tc6);
assertArrayEquals("output did not match expected result",expectedOutput, methodOutput);
}
/**
* Schedule 7. Testcase with small transactions (2) and a deadlock.
*/
@Test
public void test_G_SmallDeadlock()
{
int expectedOutput[] = {0, 2, 2, 3, 4, 5, 6, 7, 8, 9};
//Testcases
//7) Small Deadlock Cycle
List<String> tc7 = Arrays.asList(new String[]{"W(1,2);R(2);C","W(2,5);R(1);C"});
int methodOutput[] = CC.executeSchedule(newDB(),tc7);
assertArrayEquals("output did not match expected result",expectedOutput, methodOutput);
}
/**
* Schedule 8. Testcase with three transactions (2) and a deadlock.
*/
@Test
public void test_H_ThreeTransactionsDeadlock()
{
int expectedOutput[] = {0, 9, 8, 3, 4, 5, 2, 2, 8, 9};
//Testcases
//8) Three Transactions Deadlock
List<String> tc8 = Arrays.asList(new String[]{"R(6);W(7,2);W(2,8);W(6,2);C","R(4);W(2,4);R(5);W(7,3);C","R(9);R(6);W(1,9);C"});
int methodOutput[] = CC.executeSchedule(newDB(),tc8);
assertArrayEquals("output did not match expected result",expectedOutput, methodOutput);
}
/**
* Schedule 9. Testcase with small transactions (2) and no deadlocks.
*/
@Test
public void test_I_SmallTransactionsNoDeadlock()
{
int expectedOutput[] = {0, 2, 2, 5, 4, 5, 6, 7, 8, 9};
//Testcases
//9) Small Transactions without Deadlock Testcase:
List<String> tc9 = Arrays.asList(new String[]{"W(1,2);R(2);C","W(3,5);R(4);C"});
int methodOutput[] = CC.executeSchedule(newDB(),tc9);
assertArrayEquals("output did not match expected result",expectedOutput, methodOutput);
}
/**
* Schedule 10. Testcase with deadlock between two transactions.
*/
@Test
public void test_J_TestCaseDeadlockDeadlock()
{
int expectedOutput[] = {0, 5, 3, 3, 4, 5, 6, 7, 8, 9};
//Testcases
//10) Testcase with Deadlock:
List<String> tc10 = Arrays.asList(new String[]{"W(1,5);R(2);W(2,3);R(1);C","R(2);R(1);W(1,2);C"});
int methodOutput[] = CC.executeSchedule(newDB(),tc10);
assertArrayEquals("output did not match expected result",expectedOutput, methodOutput);
}
}
@@ -0,0 +1,16 @@
package tests;
import org.junit.runner.JUnitCore;
import org.junit.runner.Result;
import org.junit.runner.notification.Failure;
public class TestDriver {
public static void main(String[] args) {
Result result = JUnitCore.runClasses(tests.CCTest.class);
for (Failure failure : result.getFailures()) {
System.out.println(failure.toString());
}
System.out.println(result.wasSuccessful());
}
}
File diff suppressed because one or more lines are too long
@@ -0,0 +1,39 @@
<html>
<head>
<TITLE>Fundamentals of Database Systems Laboratory Book - 2nd Edition - Chapter 1</TITLE>
<style type="text/css">
a { text-decoration: none }a:hover {text-decoration: none;
color: red;
background-color: #ccffcc;
font-family: helvetica, sans-serif, arial;
font-size: 16pts }
h1 {font-family: helvetica, sans-serif, arial;
color: #000080;
background-color: #EECFA1;width: 20em}
h2 {font-family: helvetica, sans-serif, arial;
color: #000080;
background-color: #EECFA1; width: 20em }
.special {fontsize: 1.5em;
color: blue }
</style></head>
<body bgcolor="#8AD6EB"alink="#0000CC"link="#0000CC"text="#000000"vlink="#0000CC">
<center>
<h3>Chapter 1 - ER Modeling Tools </h3>
</center>
<h3>Laboratory Manual Chapter</h3>
<ul>
<li><a href="ch1.pdf">Chapter 1 (pdf)</a>
</ul>
<h3>ERWin design files</h3>
<ul>
<li><a href="company.erwin">company.erwin</a>
<li><a href="vehicles.erwin">vehicles.erwin</a>
</ul>
</body>
</html>
@@ -0,0 +1,25 @@
6
Research
5
333445555
22-MAY-1978
Administration
4
987654321
01-JAN-1985
Headquarters
1
888665555
19-JUN-1971
Software
6
111111100
15-MAY-1999
Hardware
7
444444400
15-MAY-1998
Sales
8
555555500
01-JAN-1997
@@ -0,0 +1,56 @@
11
333445555
Alice
F
05-APR-1976
Daughter
333445555
Theodore
M
25-OCT-1973
Son
333445555
Joy
F
03-MAY-1948
Spouse
987654321
Abner
M
29-FEB-1932
Spouse
123456789
Michael
M
01-JAN-1978
Son
123456789
Alice
F
31-DEC-1978
Daughter
123456789
Elizabeth
F
05-MAY-1957
Spouse
444444400
Johnny
M
04-APR-1997
Son
444444400
Tommy
M
07-JUN-1999
Son
444444401
Chris
M
19-APR-1969
Spouse
444444402
Alec
M
14-FEB-1964
Spouse
@@ -0,0 +1,27 @@
13
1
Houston
4
Stafford
5
Bellaire
5
Sugarland
5
Houston
6
Atlanta
6
Sacramento
7
Milwaukee
8
Chicago
8
Dallas
8
Philadephia
8
Seattle
8
Miami
@@ -0,0 +1,401 @@
40
James
E
Borg
888665555
10-NOV-27
450 Stone, Houston, TX
M
55000
null
1
Franklin
T
Wong
333445555
08-DEC-45
638 Voss, Houston, TX
M
40000
888665555
5
Jennifer
S
Wallace
987654321
20-JUN-31
291 Berry, Bellaire, TX
F
43000
888665555
4
John
B
Smith
123456789
09-Jan-55
731 Fondren, Houston, TX
M
30000
333445555
5
Alicia
J
Zelaya
999887777
19-JUL-58
3321 Castle, Spring, TX
F
25000
987654321
4
Ramesh
K
Narayan
666884444
15-SEP-52
971 Fire Oak, Humble, TX
M
38000
333445555
5
Joyce
A
English
453453453
31-JUL-62
5631 Rice, Houston, TX
F
25000
333445555
5
Ahmad
V
Jabbar
987987987
29-MAR-59
980 Dallas, Houston, TX
M
25000
987654321
4
Jared
D
James
111111100
10-OCT-1966
123 Peachtree, Atlanta, GA
M
85000
null
6
Alex
D
Freed
444444400
09-OCT-1950
4333 Pillsbury, Milwaukee, WI
M
89000
null
7
John
C
James
555555500
30-JUN-1975
7676 Bloomington, Sacramento, CA
M
81000
null
6
Jon
C
Jones
111111101
14-NOV-1967
111 Allgood, Atlanta, GA
M
45000
111111100
6
Justin
null
Mark
111111102
12-JAN-1966
2342 May, Atlanta, GA
M
40000
111111100
6
Brad
C
Knight
111111103
13-FEB-1968
176 Main St., Atlanta, GA
M
44000
111111100
6
Evan
E
Wallis
222222200
16-JAN-1958
134 Pelham, Milwaukee, WI
M
92000
null
7
Josh
U
Zell
222222201
22-MAY-1954
266 McGrady, Milwaukee, WI
M
56000
222222200
7
Andy
C
Vile
222222202
21-JUN-1944
1967 Jordan, Milwaukee, WI
M
53000
222222200
7
Tom
G
Brand
222222203
16-DEC-1966
112 Third St, Milwaukee, WI
M
62500
222222200
7
Jenny
F
Vos
222222204
11-NOV-1967
263 Mayberry, Milwaukee, WI
F
61000
222222201
7
Chris
A
Carter
222222205
21-MAR-1960
565 Jordan, Milwaukee, WI
F
43000
222222201
7
Kim
C
Grace
333333300
23-OCT-1970
6677 Mills Ave, Sacramento, CA
F
79000
null
6
Jeff
H
Chase
333333301
07-JAN-1970
145 Bradbury, Sacramento, CA
M
44000
333333300
6
Bonnie
S
Bays
444444401
19-JUN-1956
111 Hollow, Milwaukee, WI
F
70000
444444400
7
Alec
C
Best
444444402
18-JUN-1966
233 Solid, Milwaukee, WI
M
60000
444444400
7
Sam
S
Snedden
444444403
31-JUL-1977
987 Windy St, Milwaukee, WI
M
48000
444444400
7
Nandita
K
Ball
555555501
16-APR-1969
222 Howard, Sacramento, CA
M
62000
555555500
6
Bob
B
Bender
666666600
17-APR-1968
8794 Garfield, Chicago, IL
M
96000
null
8
Jill
J
Jarvis
666666601
14-JAN-1966
6234 Lincoln, Chicago, IL
F
36000
666666600
8
Kate
W
King
666666602
16-APR-1966
1976 Boone Trace, Chicago, IL
F
44000
666666600
8
Lyle
G
Leslie
666666603
09-JUN-1963
417 Hancock Ave, Chicago, IL
M
41000
666666601
8
Billie
J
King
666666604
01-JAN-1960
556 Washington, Chicago, IL
F
38000
666666603
8
Jon
A
Kramer
666666605
22-AUG-1964
1988 Windy Creek, Seattle, WA
M
41500
666666603
8
Ray
H
King
666666606
16-AUG-1949
213 Delk Road, Seattle, WA
M
44500
666666604
8
Gerald
D
Small
666666607
15-MAY-1962
122 Ball Street, Dallas, TX
M
29000
666666602
8
Arnold
A
Head
666666608
19-MAY-1967
233 Spring St, Dallas, TX
M
33000
666666602
8
Helga
C
Pataki
666666609
11-MAR-1969
101 Holyoke St, Dallas, TX
F
32000
666666602
8
Naveen
B
Drew
666666610
23-MAY-1970
198 Elm St, Philadelphia, PA
M
34000
666666607
8
Carl
E
Reedy
666666611
21-JUN-1977
213 Ball St, Philadelphia, PA
M
32000
666666610
8
Sammy
G
Hall
666666612
11-JAN-1970
433 Main Street, Miami, FL
M
37000
666666611
8
Red
A
Bacher
666666613
21-MAY-1980
196 Elm Street, Miami, FL
M
33500
666666612
8
@@ -0,0 +1,45 @@
11
ProductX
1
Bellaire
5
ProductY
2
Sugarland
5
ProductZ
3
Houston
5
Computerization
10
Stafford
4
Reorganization
20
Houston
1
Newbenefits
30
Stafford
4
OperatingSystems
61
Jacksonville
6
DatabaseSystems
62
Birmingham
6
Middleware
63
Jackson
6
InkjetPrinters
91
Phoenix
7
LaserPrinters
92
LasVegas
7
@@ -0,0 +1,145 @@
48
123456789
1
32.5
123456789
2
7.5
666884444
3
40.0
453453453
1
20.0
453453453
2
20.0
333445555
2
10.0
333445555
3
10.0
333445555
10
10.0
333445555
20
10.0
999887777
30
30.0
999887777
10
10.0
987987987
10
35.0
987987987
30
5.0
987654321
30
20.0
987654321
20
15.0
888665555
20
0
111111100
61
40.0
111111101
61
40.0
111111102
61
40.0
111111103
61
40.0
222222200
62
40.0
222222201
62
48.0
222222202
62
40.0
222222203
62
40.0
222222204
62
40.0
222222205
62
40.0
333333300
63
40.0
333333301
63
46.0
444444400
91
40.0
444444401
91
40.0
444444402
91
40.0
444444403
91
40.0
555555500
92
40.0
555555501
92
44.0
666666601
91
40.0
666666603
91
40.0
666666604
91
40.0
666666605
92
40.0
666666606
91
40.0
666666607
61
40.0
666666608
62
40.0
666666609
63
40.0
666666610
61
40.0
666666611
61
40.0
666666612
61
40.0
666666613
61
30.0
666666613
62
10.0
666666613
63
10.0
@@ -0,0 +1,69 @@
6
EMPLOYEE
10
FNAME
VARCHAR
MINIT
VARCHAR
LNAME
VARCHAR
SSN
VARCHAR
BDATE
VARCHAR
ADDRESS
VARCHAR
SEX
VARCHAR
SALARY
DECIMAL
SUPERSSN
VARCHAR
DNO
INTEGER
DEPARTMENT
4
DNAME
VARCHAR
DNUMBER
INTEGER
MGRSSN
VARCHAR
MGRSTARTDATE
VARCHAR
DEPT_LOCATIONS
2
DNUMBER
INTEGER
DLOCATION
VARCHAR
PROJECTS
4
PNAME
VARCHAR
PNUMBER
INTEGER
PLOCATION
VARCHAR
DNUM
INTEGER
WORKS_ON
3
ESSN
VARCHAR
PNO
INTEGER
HOURS
DECIMAL
DEPENDENT
5
ESSN
VARCHAR
DEPENDENT_NAME
VARCHAR
SEX
VARCHAR
BDATE
VARCHAR
RELATIONSHIP
VARCHAR
@@ -0,0 +1,22 @@
7
CSc1010
sp04
02011000
CSc1010
f05
02011000
CSc1010
sp05
02011000
CSc4710
sp05
02012000
CSc4710
sp06
02021000
CIS6710
sp05
02013000
CIS8710
sp05
02012000
@@ -0,0 +1,16 @@
5
CSc1010
Computers and Applications
Computer Science
CSc2310
Java
Computer Science
CSc4710
Databases
Computer Science
CIS6710
Databases Programming
Computer Information Systems
CIS8710
Databases
Computer Information Systems
@@ -0,0 +1,21 @@
5
1111
CSc1010
sp04
A
1111
CSc4710
sp06
B
2222
CSc1010
sp04
A
2222
CIS6710
sp04
A
3333
CSc1010
sp04
C
@@ -0,0 +1,17 @@
4
1111
Linekar
CSc
10-20-1982
2222
Holmes
CSc
12-10-1983
3333
Tyson
Math
09-21-1985
4444
Blackwell
CSc
01-22-1980
@@ -0,0 +1,17 @@
4
02011000
Intro to Computers
Smith
Addison Wesley
02012000
Database Fundamentals
Navathe
Addison Wesley
02021000
Database Concepts
Silberschatz
McGraw Hill
02013000
Database Programming
Navathe
Addison Wesley
@@ -0,0 +1,47 @@
5
STUDENT
4
SSN
INTEGER
NAME
VARCHAR
MAJOR
VARCHAR
BDATE
VARCHAR
COURSE
3
COURSENUM
VARCHAR
CNAME
VARCHAR
DEPT
VARCHAR
ENROLL
4
SSN
INTEGER
COURSENUM
VARCHAR
QUARTER
VARCHAR
GRADE
VARCHAR
BOOKADOPTION
3
COURSENUM
VARCHAR
QUARTER
VARCHAR
BOOKISBN
INTEGER
TEXT
4
BOOKISBN
INTEGER
BOOKTITLE
VARCHAR
PUBLISHER
VARCHAR
AUTHOR
VARCHAR
@@ -0,0 +1,72 @@
Query 1: Get names of all employees in department 5 who work more than 10 hours/week on the ProductX project.
answer(F,M,L) :-
employee(F,M,L,S,_,_,_,_,_,5),
works_on(S,P,H),
projects('ProductX',P,_,_),
H >= 10.
Query 2: Get names of all employees who have a dependent with the same first name as their own first names.
answer(F,M,L) :-
employee(F,M,L,S,_,_,_,_,_,_),
dependent(S,F,_,_,_).
Query 3: Get the names of all employees who are directly supervised by Franklin Wong.
answer(F,M,L) :-
employee(F,M,L,_,_,_,_,_,S,_),
employee('Franklin',_,'Wong',S,_,_,_,_,_,_).
Query 4: Get the names of all employees who work on every project.
temp1(S,P) :-
employee(_,_,_,S,_,_,_,_,_,_),
projects(_,P,_,_).
temp2(S,P) :-
works_on(S,P,_).
temp3(S) :-
temp1(S,P), not temp2(S,P).
answer(F,M,L) :-
employee(F,M,L,S,_,_,_,_,_,_), not temp3(S).
Query 5: Get the names of employees who do not work on any project.
temp1(S) :-
works_on(S,_,_).
answer(F,M,L) :-
employee(F,M,L,S,_,_,_,_,_,_), not temp1(S).
Query 6: Get the names and addresses of employees who work for at least one project located in Houston but whose department does not have a location in Houston.
temp1(S) :-
works_on(S,P,_), project(_,P,'Houston',_).
temp2(S) :-
employee(_,_,_,S,_,_,_,_,_,D),
not dept_locations(D,'Houston').
answer(F,M,L,A) :-
employee(F,M,L,S,_,A,_,_,_,_), temp1(S), temp2(S).
Query 7: Get the names and addresses of employees who work for at least one project located in Houston or whose department does not have a location in Houston. (Note: this is a slight variation of the previous query with 'but' replaced by 'or').
temp1(S) :-
works_on(S,P,_),
project(_,P,'Houston',_).
temp2(S) :-
employee(_,_,_,S,_,_,_,_,_,D),
not dept_locations(D,'Houston').
answer(F,M,L,A) :-
employee(F,M,L,S,_,A,_,_,_,_), temp1(S).
answer(F,M,L,A) :-
employee(F,M,L,S,_,A,_,_,_,_), temp2(S).
Query 8: Get the last names of all department managers who have no dependents.
temp1(S) :-
dependent(S,_,_,_,_).
answer(L) :-
employee(_,_,L,S,_,_,_,_,_,_),
department(_,_,S,_),
not temp1(S).
@@ -0,0 +1,40 @@
Query 0: Retrieve the birthdate and address of the employees whose name is "John B. Smith".
{ u,v | (exists t,w,x,y,z)(
employee('John','B','Smith',t,u,v,w,x,y,z) ) }
Query 1: Retrieve the name and address of all employees who work for the "Research"
department.
{ q,s,v | (exists r,t,u,w,x,y,z,n,o)(
employee(q,r,s,t,u,v,w,x,y,z) and
department('Research',z,n,o) ) }
Query 2: For every project located in "Stafford", list the project number, the
controlling department number, and the department manager's last name,
birth date, and address.
{ i,k,s,u,v | (exists h,q,r,t,w,x,y,z,l,o)(
projects(h,i,'Stafford',k) and
employee(q,r,s,t,u,v,w,x,y,z) and
department(l,k,t,o) ) }
Query 6: List the names of employees who have no dependents.
{ q,s | (exists r,t,u,v,w,x,y,z)(
employee(q,r,s,t,u,v,w,x,y,z) and
not ((exists m,n,o,p)(dependent(t,m,n,o,p))) ) }
The following is not SAFE and would not work
{ q,s | (exists r,t,u,v,w,x,y,z)(
employee(q,r,s,t,u,v,w,x,y,z) and
(forall l,m,n,o,p)(not (dependent(l,m,n,o,p)) or t<>l) )}
Query 7: List the names of managers who have at least one dependent.
{ s,q | (exists r,t,u,v,w,x,y,z,h,i,k,m,n,o,p)(
employee(q,r,s,t,u,v,w,x,y,z) and
department(h,i,t,k) and
dependent(t,m,n,o,p) ) }

Some files were not shown because too many files have changed in this diff Show More